> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corelink.dhi-cm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Push Sync/Async 

> API Connecteur -> banque, la banque expose API

## Création d’un ordre de paiement

Le Connecteur transmet les ordres de paiement via une requête **HTTP POST sécurisée**.\
Les informations de sécurité sont portées **exclusivement par les en-têtes HTTP** et font référence au corps JSON signé.

| En-tête             | Description                         |
| :------------------ | :---------------------------------- |
| `X-Client-Id`       | Identifiant technique du connecteur |
| `X-Request-Id`      | Identifiant technique de la requete |
| `X-Timestamp`       | Horodatage ISO 8601 UTC             |
| `X-Nonce`           | Identifiant unique anti-rejeu       |
| `X-Idempotency-Key` | Clé d’idempotence métier            |
| `X-Signature`       | Signature cryptographique du corps  |
| `Authorization`     | OAuth2 (Bearer / DPoP )             |
| `Content-Type`      | `application/json`                  |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.bank.example.com/payment-orders \
    -H "Content-Type: application/json" \
    -H "X-Client-Id: CONNECTOR_X" \
    -H "X-Timestamp: 2025-11-19T07:05:00Z" \
    -H "X-Nonce: 550e8400-e29b-41d4-a716-446655440000" \
    -H "X-Idempotency-Key: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
    -H "X-Signature: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9..." \
    -H "Authorization: Bearer <access_token>" \
    -d @payload.json
  ```

  ```java Java theme={null}
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.APPLICATION_JSON);
  headers.set("X-Client-Id", "CONNECTOR_X");
  headers.set("X-Timestamp", "2025-11-19T07:05:00Z");
  headers.set("X-Nonce", UUID.randomUUID().toString());
  headers.set("X-Idempotency-Key", orderId);
  headers.set("X-Signature", signature);
  headers.setBearerAuth(accessToken);

  HttpEntity<String> request =
          new HttpEntity<>(payloadJson, headers);

  ResponseEntity<String> response =
          restTemplate.postForEntity(
                  "https://api.bank.example.com/payment-orders",
                  request,
                  String.class
          );
  ```

  ```python Python theme={null}
  import requests
  import uuid

  headers = {
      "Content-Type": "application/json",
      "X-Client-Id": "CONNECTOR_X",
      "X-Timestamp": "2025-11-19T07:05:00Z",
      "X-Nonce": str(uuid.uuid4()),
      "X-Idempotency-Key": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "X-Signature": signature,
      "Authorization": f"Bearer {access_token}"
  }

  response = requests.post(
      "https://api.bank.example.com/payment-orders",
      json=payload,
      headers=headers,
      timeout=10
  )

  response.raise_for_status()
  ```

  ```node Node - Axios theme={null}
  import axios from "axios";
  import { v4 as uuidv4 } from "uuid";

  await axios.post(
    "https://api.bank.example.com/payment-orders",
    payload,
    {
      headers: {
        "Content-Type": "application/json",
        "X-Request-Id": uuidv4(),
        "X-Client-Id": "CONNECTOR_X",
        "X-Timestamp": "2025-11-19T07:05:00Z",
        "X-Nonce": uuidv4(),
        "X-Idempotency-Key": orderId,
        "X-Signature": signature,
        "Authorization": `Bearer ${accessToken}`
      },
      timeout: 10000
    }
  );
  ```
</CodeGroup>

## Réponse attendue du service bancaire

Le service bancaire **DOIT** retourner une réponse HTTP conforme aux règles décrites ci-dessous.\
Le **code HTTP** détermine **explicitement** la présence ou non d’un corps de réponse.

| HTTP Status              | Signification                        | Corps de réponse        |
| :----------------------- | :----------------------------------- | :---------------------- |
| **200 OK (sync)**        | Traitement en cours ou terminé       | **OBLIGATOIRE**         |
| **202 Accepted (async)** | Traitement accepté, résultat différé | **ABSENT**              |
| **4xx / 5xx**            | Erreur                               | Objet d’erreur standard |

Toute déviation à ces règles entraîne un rejet de l’intégration.

## Cas 1 — HTTP 202 Accepted (traitement asynchrone)

### Description

Le code **202 Accepted** indique que :

* l’ordre a été **accepté techniquement**,
* le traitement bancaire est **différé**,
* **aucun statut métier final n’est encore disponible**.

### Règle obligatoire

* **Aucun corps de réponse ne doit être retourné**
* Le header `Content-Length` doit être égal à `0`
* Le statut final **DEVRA** être transmis ultérieurement via **callback**

## Cas 2 — HTTP 200 OK (traitement synchrone)

### Description

Le code **200 OK** indique que :

* l’ordre a été traité **immédiatement**,
* un **statut métier est disponible**,
* le résultat est **définitif**.

### Règle obligatoire

* Le corps de réponse est **OBLIGATOIRE**
* Le corps **DOIT** respecter le format standard décrit ci-dessous

## Format du corps de réponse (HTTP 200)

```json theme={null}
{
  "status": "PENDING | SUCCESS | FAILED",
  "reference": "string",
  "bank_reference": "string",
  "timestamp": "2025-11-19T07:06:30Z",
  "reason_code": "xxxx",
  "reason_message" : "yyyy"
}
```

| Champ            | Type         | Obligatoire  | Description                        |
| :--------------- | :----------- | :----------- | :--------------------------------- |
| `status`         | String       | Oui          | Statut métier du paiement          |
| `reference`      | String       | Oui          | Référence initiale de l’ordre      |
| `bank_reference` | String       | Oui          | Référence bancaire interne         |
| `reason_code`    | String       | Conditionnel | Obligatoire si `status = FAILED`   |
| `reason_message` | String       | Conditionnel | Message lisible expliquant l’échec |
| `timestamp`      | ISO 8601 UTC | Oui          | Date de traitement bancaire        |

Règles sur le champ `status`

| Valeur    | Signification                            |
| :-------- | :--------------------------------------- |
| `PENDING` | Traitement initié, finalisation différée |
| `SUCCESS` | Paiement exécuté avec succès             |
| `FAILED`  | Paiement rejeté ou échoué                |

### Contraintes

* `SUCCESS` et `FAILED` sont **des statuts finaux**
* `PENDING` implique **obligatoirement** un callback ultérieur
* Un statut final **ne peut jamais être modifié**

## Cas particulier — FAILED

Lorsque `status = FAILED` :

* `reasonCode` est **OBLIGATOIRE**
* `reasonMessage` est **OBLIGATOIRE**
* Le code doit appartenir à la nomenclature des **erreurs métier documentées**

Example

```json theme={null}
{
  "status": "FAILED",
  "reference": "PAY-2025-0001",
  "bank_reference": "BNK-778899",
  "reason_code": "BUS_INSUFFICIENT_FUNDS",
  "reason_message": "Insufficient balance on debtor account.",
  "timestamp": "2025-11-19T07:06:30Z"
}
```

## Règles de cohérence (IMPORTANT)

* Un **HTTP 200 sans body est invalide**
* Un **HTTP 202 avec body est invalide**
* Le `reference` DOIT correspondre exactement à la référence reçue
* Le `bank_reference` est obligatoire pour toute traçabilité bancaire
* Le timestamp DOIT être exprimé en UTC

## Cas 3 — HTTP 4xx/5xx

Gestion d'erreur standard
