# Journal des modifications

Chaque version de l’API AdProMaxPay, ce qu’elle contient, et si elle casse du code existant.

Cette page liste chaque version de l’API, de la plus récente à la plus ancienne. Chaque entrée dit si
elle est **incompatible** : si le code écrit pour la version précédente doit changer.

## Comment marchent les versions

* Une version porte le nom de sa date : `2026-11-01`.
* Votre organisation est **fixée** sur la version en cours au moment de sa création. Son
  `api_version`, dans `GET /v1/account`, la nomme. Vos requêtes l’utilisent sauf si elles disent
  autre chose.
* Une requête peut nommer une version avec l’en-tête `X-AdProMaxPay-Version`. Une version inconnue est
  refusée avec `400`, `api_version_invalid`.
* Chaque événement porte l’`api_version` avec laquelle il a été écrit.

Un **changement incompatible** arrive dans une nouvelle version datée, et la version sur laquelle
vous êtes fixé continue de fonctionner comme avant. Les **ajouts** arrivent sans nouvelle version :
nouveaux objets, nouveaux champs, nouveaux types d’événements, nouveaux paramètres facultatifs et
nouveaux codes d’erreur. Écrivez votre code pour qu’il ignore les champs et les types d’événements
qu’il ne connaît pas.

```bash
curl https://pay-api.adpromax.com/v1/account \
  -u "$APX_SECRET_KEY:" \
  -H "X-AdProMaxPay-Version: 2026-11-01"
```

```js title="version.mjs"
const response = await fetch('https://pay-api.adpromax.com/v1/account', {
  headers: {
    'Authorization': `Bearer ${process.env.APX_SECRET_KEY}`,
    'X-AdProMaxPay-Version': '2026-11-01',
  },
})
const account = await response.json()
console.log(account.api_version)
```

```ts title="version.ts"
interface Account {
  id: string
  object: 'account'
  api_version: string
}

const response = await fetch('https://pay-api.adpromax.com/v1/account', {
  headers: {
    'Authorization': `Bearer ${process.env.APX_SECRET_KEY}`,
    'X-AdProMaxPay-Version': '2026-11-01',
  },
})
const account = (await response.json()) as Account
console.log(account.api_version)
```

```python title="version.py"
import os

import requests

response = requests.get(
    "https://pay-api.adpromax.com/v1/account",
    auth=(os.environ["APX_SECRET_KEY"], ""),
    headers={"X-AdProMaxPay-Version": "2026-11-01"},
)
account = response.json()
print(account["api_version"])
```

```php title="version.php"
<?php
$ch = curl_init('https://pay-api.adpromax.com/v1/account');
curl_setopt_array($ch, [
    CURLOPT_USERPWD => getenv('APX_SECRET_KEY') . ':',
    CURLOPT_HTTPHEADER => ['X-AdProMaxPay-Version: 2026-11-01'],
    CURLOPT_RETURNTRANSFER => true,
]);
$account = json_decode(curl_exec($ch), true);
echo $account['api_version'], PHP_EOL;
```

```ruby title="version.rb"
require 'json'
require 'net/http'

uri = URI('https://pay-api.adpromax.com/v1/account')
request = Net::HTTP::Get.new(uri)
request.basic_auth(ENV.fetch('APX_SECRET_KEY'), '')
request['X-AdProMaxPay-Version'] = '2026-11-01'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(request)
end
account = JSON.parse(response.body)
puts account['api_version']
```

```go title="version.go"
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type Account struct {
	ID         string `json:"id"`
	APIVersion string `json:"api_version"`
}

func main() {
	req, err := http.NewRequest(http.MethodGet, "https://pay-api.adpromax.com/v1/account", nil)
	if err != nil {
		log.Fatal(err)
	}
	req.SetBasicAuth(os.Getenv("APX_SECRET_KEY"), "")
	req.Header.Set("X-AdProMaxPay-Version", "2026-11-01")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()

	var account Account
	if err := json.NewDecoder(res.Body).Decode(&account); err != nil {
		log.Fatal(err)
	}
	fmt.Println(account.APIVersion)
}
```

```java title="Version.java"
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Version {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://pay-api.adpromax.com/v1/account"))
            .header("Authorization", "Bearer " + System.getenv("APX_SECRET_KEY"))
            .header("X-AdProMaxPay-Version", "2026-11-01")
            .GET()
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        // The JDK has no JSON parser: a small regex reads api_version.
        Matcher version = Pattern
            .compile("\"api_version\"\\s*:\\s*\"([^\"]*)\"")
            .matcher(response.body());
        System.out.println(version.find() ? version.group(1) : response.body());
    }
}
```

```csharp title="Version.cs"
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;

var json = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("APX_SECRET_KEY"));
http.DefaultRequestHeaders.Add("X-AdProMaxPay-Version", "2026-11-01");

var account = await http.GetFromJsonAsync<Account>("https://pay-api.adpromax.com/v1/account", json);
Console.WriteLine(account!.ApiVersion);

record Account(string Id, string ApiVersion);
```

```rust title="main.rs"
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
//             serde = { version = "1", features = ["derive"] }
use serde::Deserialize;

#[derive(Deserialize)]
struct Account {
    api_version: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let account: Account = reqwest::blocking::Client::new()
        .get("https://pay-api.adpromax.com/v1/account")
        .bearer_auth(std::env::var("APX_SECRET_KEY")?)
        .header("X-AdProMaxPay-Version", "2026-11-01")
        .send()?
        .json()?;
    println!("{}", account.api_version);
    Ok(())
}
```

## 2026-11-01

**Compatible** : la première version de l’API. Elle contient :

* **Le compte** : `GET /v1/account`, votre organisation et son statut d’activation. Voir
  [Vos clés d’API](https://pay-docs.adpromax.com/fr/get-started/api-keys).
* **Les intentions de paiement et les tentatives**, par carte et en espèces, avec leurs statuts.
  Voir [Le fonctionnement des paiements](https://pay-docs.adpromax.com/fr/payments/how-payments-work).
* **Les sessions de paiement**, pour la page de paiement hébergée. Voir
  [Page de paiement hébergée](https://pay-docs.adpromax.com/fr/payments/hosted-checkout).
* **Les clients**. Voir [Clients](https://pay-docs.adpromax.com/fr/payments/customers).
* **Les remboursements** des paiements par carte. Voir [Remboursements](https://pay-docs.adpromax.com/fr/payments/refunds).
* **Les événements et les endpoints de webhook** : envois signés, retentés pendant environ trois
  jours. Voir [Webhooks](https://pay-docs.adpromax.com/fr/webhooks).
* **Les assistants de test**, en mode test uniquement. Voir
  [API des assistants de test](https://pay-docs.adpromax.com/fr/sandbox/test-helpers).
* **L’idempotence** : obligatoire sur les requêtes qui déplacent de l’argent, réponses gardées
  24 heures. Voir [Idempotence](https://pay-docs.adpromax.com/fr/api-reference/idempotency).
* **Les erreurs** en sept types, avec des messages en français, en anglais ou en arabe, d’après
  l’en-tête `Accept-Language`. Voir [Gérer les erreurs](https://pay-docs.adpromax.com/fr/errors).
* **La pagination par curseur** sur les listes : `limit`, `starting_after` et `ending_before`.
* **Les limites de débit** par organisation et par mode, avec les en-têtes `RateLimit-*`. Voir
  [Limites de débit](https://pay-docs.adpromax.com/fr/api-reference/rate-limits).
* **Les métadonnées** sur les intentions de paiement, les sessions de paiement, les clients, les
  remboursements et les endpoints de webhook. Voir [Métadonnées](https://pay-docs.adpromax.com/fr/payments/metadata).
