Linc, retour à l'accueil

Développeurs

Intégrez Linc à votre application

Une API REST en JSON pour envoyer de l'argent, encaisser des paiements, gérer des cartes virtuelles et recevoir des notifications signées. Toutes les requêtes passent en HTTPS. Aucune donnée de carte ne transite par vos serveurs.

Démarrer

EnvironnementURL de baseUsage
Sandboxhttps://sandbox.api.linc.cdDéveloppement et tests. Clés sk_test_…, aucun argent réel, partenaires simulés.
Productionhttps://api.linc.cdOpérations réelles. Clés sk_live_…, ouvertes après validation de votre dossier.

Toutes les routes commencent par /v1. Le corps des requêtes et des réponses est en JSON (UTF-8). Vous pouvez appeler l'API depuis n'importe quel langage capable de faire une requête HTTPS : les exemples ci-dessous sont en cURL, PHP, Python et JavaScript (Node.js 18+).

  1. Ouvrez un compte marchand sur merchant.linc.cd. Vos clés de test sont disponibles tout de suite.
  2. Récupérez vos clés dans Espace marchand › API & webhooks. La clé secrète s'affiche une seule fois : conservez-la dans un coffre ou une variable d'environnement.
  3. Déclarez l'URL de votre webhook au même endroit, puis testez sur la sandbox.
  4. Passez en production quand votre dossier (KYB) est validé : remplacez l'URL de base et la clé.

Quelle intégration choisir ?

Vous voulez…AuthentificationRoutes principales
Encaisser les paiements de vos clients (site, application, facture)Clé secrète marchand sk_/v1/payment-links
Agir au nom d'un client Linc : transferts, paiements, carte virtuelle, rechargementJeton client (JWT 15 min + jeton de renouvellement)/v1/auth, /v1/quotes, /v1/transfers, /v1/cards
Construire une application pour un marchand ou un agent LincJeton pro (mot de passe + TOTP)/v1/pro/auth
Relier la plateforme d'un réseau d'agents, de serveur à serveurBientôt : clés à portée limitée, requêtes signées et adresses IP autorisées. Écrivez à sales@linc.cd.

L'API client agit toujours pour un client identifié, qui confirme lui-même chaque opération sensible avec son second facteur. Linc ne délivre jamais de jeton client à un tiers sans le consentement du client.

Authentification

Clé secrète marchand

Envoyez la clé dans l'en-tête Authorization. Une clé absente ou invalide répond 401 api_key_invalid. N'utilisez jamais la clé secrète dans un navigateur ou une application mobile : elle reste sur votre serveur.

curl https://sandbox.api.linc.cd/v1/payment-links/INV-7K2Q4F \
  -H "Authorization: Bearer $LINC_SECRET_KEY"

Adresses IP autorisées

Les clés secrètes ne fonctionnent que depuis les adresses IP de vos serveurs. Déclarez-les dans l'étape « Intégration technique » de votre dossier, puis gérez-les dans votre espace marchand, « API & webhooks › Adresses IP autorisées ». Chaque modification est confirmée par votre application d'authentification.

  • Production (sk_live_) : la liste est obligatoire pour générer les clés. Un appel depuis une autre adresse répond 403 ip_not_allowed.
  • Sandbox (sk_test_) : la liste est facultative. Vide, toute adresse est acceptée, l'espace de test de cette page compris.
  • Jusqu'à 10 adresses IPv4 (203.0.113.10) ou IPv6 (2001:db8::10), ou plages CIDR (198.51.100.0/28 ; de /8 à /32 en IPv4, de /32 à /128 en IPv6).
  • L'adresse contrôlée est celle qui se connecte à Linc : l'adresse de sortie de votre serveur, ou de votre passerelle NAT ou proxy sortant. Un en-tête X-Forwarded-For envoyé par votre code n'est pas pris en compte.
  • Vous changez d'hébergement ? Ajoutez la nouvelle adresse avant la bascule, puis retirez l'ancienne.
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json

{"type": "https://docs.linc.cd/erreurs/ip_not_allowed", "status": 403, "code": "ip_not_allowed",
 "title": "Adresse IP non autorisée pour cette clé. Ajoutez l’adresse de votre serveur dans « API & webhooks › Adresses IP autorisées »."}

Jeton client : connexion en deux temps

  1. POST /v1/auth/login avec l'identifiant (téléphone ou e-mail) et le mot de passe, et l'en-tête X-Device-Id (identifiant stable de l'installation).
  2. Appareil connu : réponse 200 avec les jetons. Nouvel appareil : réponse 202 two_factor_required avec un pendingLoginId et les méthodes proposées (totp, sms, backup_code).
  3. Pour le SMS, demandez d'abord le code : POST /v1/auth/login/{pendingLoginId}/sms. Puis envoyez le code : POST /v1/auth/login/{pendingLoginId}/verify.
  4. Utilisez accessToken (valable 15 minutes) dans Authorization: Bearer …. Avant expiration, appelez POST /v1/auth/refresh : le jeton de renouvellement est rotatif, conservez le nouveau et jetez l'ancien.
# 1. Mot de passe
curl -X POST https://sandbox.api.linc.cd/v1/auth/login \
  -H "Content-Type: application/json" -H "X-Device-Id: $DEVICE_ID" \
  -d '{"identifier": "+243810000000", "password": "…"}'
# → 202 {"status":"two_factor_required","pendingLoginId":"0192…","methods":["totp","sms"],"expiresAt":"…"}

# 2. Second facteur
curl -X POST https://sandbox.api.linc.cd/v1/auth/login/$PENDING_ID/verify \
  -H "Content-Type: application/json" -H "X-Device-Id: $DEVICE_ID" \
  -d '{"method": "totp", "code": "123456"}'
# → 200 {"tokenType":"Bearer","accessToken":"eyJ…","expiresIn":900,"refreshToken":"…","refreshExpiresIn":…}

# 3. Renouvellement
curl -X POST https://sandbox.api.linc.cd/v1/auth/refresh \
  -H "Content-Type: application/json" -d '{"refreshToken": "…"}'
<?php
function linc(string $method, string $path, array $body = null, array $headers = []): array
{
    $ch = curl_init('https://sandbox.api.linc.cd'.$path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array_merge(['Content-Type: application/json', 'Accept: application/json'], $headers),
        CURLOPT_POSTFIELDS => null === $body ? null : json_encode($body),
    ]);
    $raw = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    return [$status, json_decode($raw, true)];
}

$device = ['X-Device-Id: '.getenv('LINC_DEVICE_ID')];
[$status, $login] = linc('POST', '/v1/auth/login', ['identifier' => '+243810000000', 'password' => $password], $device);
if (202 === $status) {
    [, $login] = linc('POST', "/v1/auth/login/{$login['pendingLoginId']}/verify", ['method' => 'totp', 'code' => $totpCode], $device);
}
$auth = ['Authorization: Bearer '.$login['accessToken']];
import os, requests

API = "https://sandbox.api.linc.cd"
device = {"X-Device-Id": os.environ["LINC_DEVICE_ID"]}

r = requests.post(f"{API}/v1/auth/login", json={"identifier": "+243810000000", "password": password}, headers=device, timeout=30)
if r.status_code == 202:
    pending = r.json()["pendingLoginId"]
    r = requests.post(f"{API}/v1/auth/login/{pending}/verify", json={"method": "totp", "code": totp_code}, headers=device, timeout=30)
r.raise_for_status()
tokens = r.json()
auth = {"Authorization": f"Bearer {tokens['accessToken']}"}
const API = "https://sandbox.api.linc.cd";
const device = { "Content-Type": "application/json", "X-Device-Id": process.env.LINC_DEVICE_ID };

let res = await fetch(`${API}/v1/auth/login`, {
  method: "POST", headers: device,
  body: JSON.stringify({ identifier: "+243810000000", password }),
});
if (res.status === 202) {
  const { pendingLoginId } = await res.json();
  res = await fetch(`${API}/v1/auth/login/${pendingLoginId}/verify`, {
    method: "POST", headers: device,
    body: JSON.stringify({ method: "totp", code: totpCode }),
  });
}
const { accessToken, refreshToken } = await res.json();
const auth = { Authorization: `Bearer ${accessToken}` };

Conventions

Idempotence
Chaque POST financier exige l'en-tête Idempotency-Key (8 à 255 caractères, un UUID par opération). La clé est conservée 24 heures : renvoyer la même requête avec la même clé ne crée pas de doublon. La même clé avec un corps différent répond idempotency_key_reused.
Montants
En entrée, une chaîne décimale : "150.00". En sortie, un objet {"amount": 15000, "currency": "USD", "display": "150,00 $"} où amount est un entier en unités mineures. N'utilisez jamais de nombre à virgule flottante pour de l'argent.
Devises et pays
Codes ISO 4217 (USD, CDF) et ISO 3166 alpha-2 (CI, SN…). Les pays et modes de réception ouverts se lisent sur GET /v1/corridors (public).
Second facteur
Les opérations sensibles (transfert, paiement, carte, bénéficiaire) prennent un objet "twoFactor": {"method": "totp", "code": "••••••"}. Sans lui, la réponse est two_factor_required : demandez le code au client, puis renvoyez la requête avec la même Idempotency-Key.
Applications mobiles
Envoyez X-Device-Id, X-App-Id, X-App-Platform et X-App-Version. Quand la politique l'exige, les opérations sensibles demandent aussi X-Linc-Attestation (appareil attesté).
Asynchrone
Un transfert ou un paiement est accepté (202) puis traité : suivez son état par webhook ou par GET, jamais en supposant qu'il a réussi.

Faire un transfert

Exemple : 150 USD depuis Airtel Money (RDC) vers un Orange Money en Côte d'Ivoire.

1Montant et paysLe client choisit le pays et le mode de réception.
2DevisFrais, taux, total débité, montant reçu. Valable 60 s.
3BénéficiaireNuméro mobile money, compte bancaire ou carte.
4ConfirmationSource de fonds et code à 6 chiffres (2FA).
5SuiviCollecte, versement, livraison, en temps réel.
  1. POST /v1/quotes : montant, devise, pays et mode de réception. Réponse : id, send, fee, vat, levy, total, receive, rate, expiresAt. Affichez-les tels quels au client.
  2. POST /v1/beneficiaries (une seule fois par bénéficiaire) : nom, pays, mode et coordonnées dans details.
  3. POST /v1/transfers avant l'expiration du devis : quoteId, beneficiaryId, source, purpose et twoFactor. Réponse 202 avec la référence LP-XXXXXX.
  4. GET /v1/transfers/{reference} : status vaut in_progress, delivered, failed, refunded ou on_hold, avec les étapes.
# 1. Devis
curl -X POST https://sandbox.api.linc.cd/v1/quotes \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"amount": "150.00", "currency": "USD", "destinationCountry": "CI", "payoutMethod": "mobile_money", "sourceType": "mobile_money"}'

# 2. Bénéficiaire
curl -X POST https://sandbox.api.linc.cd/v1/beneficiaries \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  -d '{"fullName": "Bastian Kelyan", "country": "CI", "payoutMethod": "mobile_money",
       "details": {"msisdn": "+2250700000000", "provider": "orange", "relationship": "family"}}'

# 3. Envoi, confirmé par le second facteur
curl -X POST https://sandbox.api.linc.cd/v1/transfers \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"quoteId": "'$QUOTE_ID'", "beneficiaryId": "'$BENEFICIARY_ID'",
       "source": {"type": "mobile_money", "provider": "airtel", "msisdn": "+243970000000"},
       "purpose": "family_support",
       "twoFactor": {"method": "totp", "code": "••••••"}}'
# → 202 {"reference": "LP-8QK2ZD", "status": "in_progress", "steps": […], …}

# 4. Suivi
curl https://sandbox.api.linc.cd/v1/transfers/LP-8QK2ZD -H "Authorization: Bearer $ACCESS_TOKEN"
<?php
// linc() : voir l'exemple d'authentification
$idem = fn () => 'Idempotency-Key: '.bin2hex(random_bytes(16));

[, $quote] = linc('POST', '/v1/quotes', [
    'amount' => '150.00', 'currency' => 'USD',
    'destinationCountry' => 'CI', 'payoutMethod' => 'mobile_money', 'sourceType' => 'mobile_money',
], [...$auth, $idem()]);
// Afficher $quote['fee']['display'], $quote['total']['display'], $quote['receive']['display']

[$status, $transfer] = linc('POST', '/v1/transfers', [
    'quoteId' => $quote['id'],
    'beneficiaryId' => $beneficiaryId,
    'source' => ['type' => 'mobile_money', 'provider' => 'airtel', 'msisdn' => '+243970000000'],
    'purpose' => 'family_support',
    'twoFactor' => ['method' => 'totp', 'code' => $code],
], [...$auth, $idem()]);

if (202 !== $status) {
    throw new RuntimeException($transfer['code'].' : '.$transfer['title']);
}
echo $transfer['reference']; // LP-XXXXXX
import uuid

def post(path, body):
    headers = {**auth, "Idempotency-Key": str(uuid.uuid4())}
    return requests.post(f"{API}{path}", json=body, headers=headers, timeout=30)

quote = post("/v1/quotes", {
    "amount": "150.00", "currency": "USD",
    "destinationCountry": "CI", "payoutMethod": "mobile_money", "sourceType": "mobile_money",
}).json()
print(quote["fee"]["display"], quote["total"]["display"], quote["receive"]["display"])

r = post("/v1/transfers", {
    "quoteId": quote["id"],
    "beneficiaryId": beneficiary_id,
    "source": {"type": "mobile_money", "provider": "airtel", "msisdn": "+243970000000"},
    "purpose": "family_support",
    "twoFactor": {"method": "totp", "code": code},
})
if r.status_code != 202:
    problem = r.json()
    raise RuntimeError(f"{problem['code']} : {problem['title']}")
reference = r.json()["reference"]  # LP-XXXXXX
import { randomUUID } from "node:crypto";

const post = (path, body) => fetch(`${API}${path}`, {
  method: "POST",
  headers: { ...auth, "Content-Type": "application/json", "Idempotency-Key": randomUUID() },
  body: JSON.stringify(body),
});

const quote = await (await post("/v1/quotes", {
  amount: "150.00", currency: "USD",
  destinationCountry: "CI", payoutMethod: "mobile_money", sourceType: "mobile_money",
})).json();

const res = await post("/v1/transfers", {
  quoteId: quote.id,
  beneficiaryId,
  source: { type: "mobile_money", provider: "airtel", msisdn: "+243970000000" },
  purpose: "family_support",
  twoFactor: { method: "totp", code },
});
if (res.status !== 202) {
  const problem = await res.json();
  throw new Error(`${problem.code} : ${problem.title}`);
}
const { reference } = await res.json(); // LP-XXXXXX

Sources possibles : mobile_money (Airtel Money, M-Pesa, Orange Money, Afrimoney), wallet (solde Linc, compte en mode wallet) et card quand ce parcours est ouvert. Destinations : mobile_money, bank_account ou card. Les pays et modes proposés dépendent des corridors ouverts : lisez-les sur GET /v1/corridors plutôt que de les coder en dur.

Encaisser un paiement (marchand)

1Votre siteVotre serveur crée le lien de paiement.
2Page LincLe client ouvre app.linc.cd/pay/INV-… ou scanne le QR.
3PaiementSolde, mobile money ou carte, confirmé par le client.
4ReçuVous recevez payment.succeeded.
  1. POST /v1/payment-links avec votre clé secrète : amount, description, expires_in (24h, 7d ou 30d). La réponse contient id (INV-XXXXXX), url et qr.
  2. Redirigez le client vers url, affichez le QR ou envoyez le lien par SMS.
  3. Livrez la commande à la réception du webhook payment.succeeded (et non au retour du client sur votre site). En secours, lisez l'état avec GET /v1/payment-links/{id} : open, paid, expired ou cancelled.
curl -X POST https://sandbox.api.linc.cd/v1/payment-links \
  -H "Authorization: Bearer $LINC_SECRET_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-10452" \
  -d '{"amount": "25.00", "description": "Commande n° 10452", "expires_in": "24h"}'
# → 201 {"id": "INV-7K2Q4F", "object": "payment_link", "status": "open", "livemode": false,
#        "amount": {"amount": 2500, "currency": "USD", "display": "25,00 $"},
#        "url": "https://app.linc.cd/pay/INV-7K2Q4F", "qr": "…", "expires_at": "…"}
<?php
[$status, $link] = linc('POST', '/v1/payment-links',
    ['amount' => '25.00', 'description' => 'Commande n° 10452', 'expires_in' => '24h'],
    ['Authorization: Bearer '.getenv('LINC_SECRET_KEY'), 'Idempotency-Key: order-10452'],
);
header('Location: '.$link['url'], true, 303);
r = requests.post(f"{API}/v1/payment-links",
    json={"amount": "25.00", "description": "Commande n° 10452", "expires_in": "24h"},
    headers={"Authorization": f"Bearer {os.environ['LINC_SECRET_KEY']}", "Idempotency-Key": "order-10452"},
    timeout=30)
r.raise_for_status()
link = r.json()
redirect_to(link["url"])  # https://app.linc.cd/pay/INV-…
const res = await fetch(`${API}/v1/payment-links`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.LINC_SECRET_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "order-10452",
  },
  body: JSON.stringify({ amount: "25.00", description: "Commande n° 10452", expires_in: "24h" }),
});
const link = await res.json();
response.redirect(303, link.url);

Un lien créé avec une clé de test (livemode: false) n'est jamais payable en réel. Côté application client, le paiement d'un lien ou d'un QR se fait avec POST /v1/merchant-payments/resolve (lire le QR ou le lien) puis POST /v1/merchant-payments (payer, avec le second facteur). Le paiement par carte bancaire passe par une page carte hébergée, avec 3-D Secure : vous ne manipulez jamais le numéro de carte.

Créer une carte virtuelle

Disponible pour un client en mode wallet avec un KYC de niveau 2. La carte est alimentée par le solde Linc.

1RéseauVisa ou Mastercard, nom sur la carte.
2ConfirmationCode à 6 chiffres (2FA).
3Carte4 derniers chiffres, statut, plafonds.
4DétailsAffichés par le widget sécurisé de l'émetteur.
curl -X POST https://sandbox.api.linc.cd/v1/cards \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"network": "visa", "embossedName": "AMANI K", "twoFactor": {"method": "totp", "code": "••••••"}}'
# → 201 {"id": "0192…", "last4": "4821", "network": "visa", "currency": "USD", "status": "active", "limits": {…}, …}

# Geler, dégeler
curl -X POST https://sandbox.api.linc.cd/v1/cards/$CARD_ID/freeze   -H "Authorization: Bearer $ACCESS_TOKEN"
curl -X POST https://sandbox.api.linc.cd/v1/cards/$CARD_ID/unfreeze -H "Authorization: Bearer $ACCESS_TOKEN"
<?php
[$status, $card] = linc('POST', '/v1/cards', [
    'network' => 'visa',
    'embossedName' => 'AMANI K',
    'twoFactor' => ['method' => 'totp', 'code' => $code],
], [...$auth, $idem()]);
echo $card['network'].' •••• '.$card['last4'];
card = post("/v1/cards", {
    "network": "visa",
    "embossedName": "AMANI K",
    "twoFactor": {"method": "totp", "code": code},
}).json()
print(card["network"], "••••", card["last4"])
const card = await (await post("/v1/cards", {
  network: "visa",
  embossedName: "AMANI K",
  twoFactor: { method: "totp", code },
})).json();
console.log(`${card.network} •••• ${card.last4}`);

Linc ne renvoie jamais le numéro complet, le CVV ni la date d'expiration. Pour les afficher, POST /v1/cards/{id}/reveal (avec le second facteur) ouvre une session de 60 secondes pour le widget ou le SDK de l'émetteur, qui affiche les détails directement au client. Autres routes : GET /v1/cards, GET /v1/cards/{id}/transactions, /replace, /terminate.

Recevoir les webhooks

Linc envoie un POST JSON à l'URL déclarée dans Espace marchand › API & webhooks (HTTPS obligatoire) à chaque évènement :

ÉvènementQuand
payment.succeededUn paiement est confirmé par le partenaire. Livrez la commande.
payment.refundedUn paiement est remboursé, en tout ou en partie.
payment.disputedUn paiement par carte fait l'objet d'une contestation.
settlement.paidLe règlement du jour est versé sur votre compte bancaire, commission déduite.

En-têtes envoyés : X-Linc-Event (type), X-Linc-Delivery (identifiant unique de l'évènement) et X-Linc-Signature :

X-Linc-Signature: t=1790712000,v1=5f1c…e9a2
# v1 = HMAC-SHA256 en hexadécimal, clé = secret du webhook (whsec_…), message = "{t}.{corps brut}"

{
  "id": "evt_0192a7c4…",
  "type": "payment.succeeded",
  "created": 1790712000,
  "merchant": "M-4K7Q2",
  "data": {
    "id": "…", "object": "payment", "status": "succeeded",
    "amount": "25.00", "currency": "USD", "commission": "0.38",
    "payment_link": "INV-7K2Q4F", "method": "mobile_money", "provider": "airtel", …
  }
}

Vérifiez toujours la signature sur le corps brut, avant de le décoder, et refusez un horodatage de plus de 5 minutes :

<?php
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_LINC_SIGNATURE'] ?? '';
$secret = getenv('LINC_WEBHOOK_SECRET');

if (1 !== preg_match('/^t=(\d+),v1=([a-f0-9]{64})$/', $header, $m)
    || abs(time() - (int) $m[1]) > 300
    || !hash_equals(hash_hmac('sha256', $m[1].'.'.$body, $secret), $m[2])) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);
// Ignorer un évènement déjà traité ($event['id']), puis traiter en file d'attente
http_response_code(200);
import hashlib, hmac, os, re, time
from flask import Flask, abort, request

app = Flask(__name__)
SECRET = os.environ["LINC_WEBHOOK_SECRET"].encode()

@app.post("/webhooks/linc")
def linc_webhook():
    body = request.get_data()  # corps brut
    m = re.fullmatch(r"t=(\d+),v1=([a-f0-9]{64})", request.headers.get("X-Linc-Signature", ""))
    if not m or abs(time.time() - int(m[1])) > 300:
        abort(400)
    expected = hmac.new(SECRET, m[1].encode() + b"." + body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, m[2]):
        abort(400)
    event = request.get_json()
    # Ignorer un évènement déjà traité (event["id"]), puis traiter en file d'attente
    return "", 200
import crypto from "node:crypto";
import express from "express";

const app = express();
app.post("/webhooks/linc", express.raw({ type: "application/json" }), (req, res) => {
  const m = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(req.get("X-Linc-Signature") ?? "");
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return res.sendStatus(400);
  const expected = crypto.createHmac("sha256", process.env.LINC_WEBHOOK_SECRET)
    .update(`${m[1]}.`).update(req.body).digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]))) return res.sendStatus(400);
  const event = JSON.parse(req.body);
  // Ignorer un évènement déjà traité (event.id), puis traiter en file d'attente
  res.sendStatus(200);
});
  • Répondez 2xx en moins de 10 secondes, puis traitez en arrière-plan.
  • Sans réponse 2xx, Linc renvoie l'évènement après 1 min, 5 min, 30 min, 2 h et 6 h.
  • Un même évènement peut arriver deux fois : dédoublonnez sur id (ou X-Linc-Delivery).
  • L'ordre d'arrivée n'est pas garanti : fiez-vous à l'état contenu dans data.
  • Le secret du webhook se renouvelle dans l'espace marchand ; les clés API aussi (rotation).

Espace de test

Vérifiez votre clé et voyez les vraies réponses de l'API, sans écrire de code. Les appels partent de votre navigateur vers la sandbox https://sandbox.api.linc.cd, qui n'accepte que les clés de test : aucun argent réel, aucun lien payable.

Saisissez uniquement une clé sk_test_…. Une clé sk_live_… est refusée avant tout envoi. La clé reste dans cette page : elle n'est ni enregistrée, ni journalisée, ni placée dans l'adresse. Fermez l'onglet pour l'effacer.

Créer un lien de paiement de test
Lire un lien de paiement

Résultat

Saisissez votre clé de test, puis cliquez sur « Vérifier la clé ».

Requête équivalente

Signer et vérifier un webhook

Testez votre code de vérification : collez le corps brut reçu et l'en-tête X-Linc-Signature, ou générez un en-tête pour un corps de test. Le calcul se fait dans votre navigateur : rien n'est envoyé. Utilisez de préférence le secret de votre webhook de test.

Fichiers JSON

Exemples de requêtes et de réponses, conformes au contrat de l'API. Téléchargez-les pour vos tests, vos maquettes d'écran ou vos simulateurs.

Collection Postman de la sandbox

Importez la collection dans Postman, puis renseignez secretKey (clé de test) ou les identifiants d'un compte de test, et deviceId. Les jetons, devis, bénéficiaires et références sont enregistrés automatiquement d'une requête à l'autre.

Authentification

Transfert

Paiement et carte

Webhooks et erreurs

Erreurs

Les erreurs suivent le format application/problem+json (RFC 9457), avec un code stable à tester dans votre code et un title lisible, en français :

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{"type": "https://docs.linc.cd/erreurs/validation_failed", "title": "Certains champs sont invalides. Corrigez-les puis réessayez.",
 "status": 422, "code": "validation_failed",
 "violations": [{"field": "amount", "message": "Saisissez un montant valide."}]}
CodeQue faire
validation_failedCorrigez les champs listés dans violations.
api_key_invalidVérifiez la clé et l'environnement (sk_test_ sur la sandbox, sk_live_ en production).
ip_not_allowedL'appel vient d'une adresse IP absente de vos adresses autorisées : ajoutez celle de votre serveur dans « API & webhooks ».
two_factor_requiredDemandez le code au client et renvoyez la requête avec twoFactor.
quote_expiredLe devis a plus de 60 secondes : demandez-en un nouveau et affichez-le au client.
quote_already_usedCe devis a déjà servi : suivez le transfert existant.
idempotency_key_requiredAjoutez l'en-tête Idempotency-Key.
idempotency_key_reusedMême clé, corps différent : générez une nouvelle clé pour une nouvelle opération.
idempotency_in_progressLa première requête est encore en cours : réessayez dans quelques secondes.
attestation_requiredEnvoyez l'assertion X-Linc-Attestation de l'appareil.
app_update_requiredMettez l'application à jour (minimumVersion).
rate_limitedTrop de requêtes : attendez, puis réessayez avec un délai croissant.

Aide et sécurité

  • Ne mettez jamais une clé secrète, un secret de webhook ou un jeton dans le code source, une application mobile ou un navigateur.
  • Journalisez le code et la référence (LP-…, INV-…), jamais les données personnelles.
  • La documentation complète, générée depuis le contrat OpenAPI, et l'espace développeur arrivent bientôt.
  • Questions techniques : support@linc.cd. Partenariats et accès production : sales@linc.cd.

POST /v1/auth/register

Créer un compte client

Crée le compte et envoie un code SMS de vérification du téléphone.

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
X-Device-Iden-têtestringnon

Identifiant d'installation de l'application. Un appareil inconnu déclenche la double authentification.

Corps de la requête

NomTypeObligatoireDescription
fullNamestringoui
phonestringoui

Numéro de téléphone, par exemple +243812345678.

emailstring (email)oui
passwordstringoui

8 caractères au moins avec un chiffre. Refusé s'il figure dans une fuite connue.

acceptTermsbooleanoui

Case « J'ai lu et j'accepte les Conditions générales d'utilisation » (versions : GET /v1/legal).

acceptPrivacybooleanoui

Case « J'ai lu la Politique de confidentialité et j'accepte le traitement de mes données décrit ».

acceptAmlbooleanoui

Case « J'ai lu la Politique LBC/FT et je m'engage à respecter mes obligations » (informations exactes, compte utilisé pour soi-même, fonds d'origine licite). Les trois cases sont distinctes, non cochées par défaut, et le serveur refuse l'inscription sans les trois (422 validation_failed, un champ par case manquante). La preuve de chaque acceptation (version, date, canal, adresse IP, appareil, session) est conservée ; le canal est la plateforme de l'application (X-App-Platform : android, ios).

residenceCountrystringnon

Pays de résidence (ISO 3166 alpha-2) parmi GET /v1/origin-countries. Par défaut, le pays du téléphone. Un autre pays est refusé (residence_not_allowed, « Linc est disponible pour les résidents de la RD Congo. »), un téléphone d'un autre pays aussi (phone_not_residence).

Exemple de requête

{
  "fullName": "texte",
  "phone": "+243810000000",
  "email": "client@example.com",
  "password": "••••••••",
  "acceptTerms": true,
  "acceptPrivacy": true,
  "acceptAml": true
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
  "fullName": "texte",
  "phone": "+243810000000",
  "email": "client@example.com",
  "password": "••••••••",
  "acceptTerms": true,
  "acceptPrivacy": true,
  "acceptAml": true
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/register');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "fullName": "texte",
  "phone": "+243810000000",
  "email": "client@example.com",
  "password": "••••••••",
  "acceptTerms": true,
  "acceptPrivacy": true,
  "acceptAml": true
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/register",
    json={
        "fullName": "texte",
        "phone": "+243810000000",
        "email": "client@example.com",
        "password": "••••••••",
        "acceptTerms": True,
        "acceptPrivacy": True,
        "acceptAml": True
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/register", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "fullName": "texte",
    "phone": "+243810000000",
    "email": "client@example.com",
    "password": "••••••••",
    "acceptTerms": true,
    "acceptPrivacy": true,
    "acceptAml": true
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "purpose": "phone_verification",
  "sentTo": "texte",
  "expiresAt": "2026-10-01T09:30:00Z",
  "remainingAttempts": 0
}

Réponses et erreurs

StatutSignification
201

Compte créé. Code SMS envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/origin-countries

Lister les pays de résidence acceptés à l'inscription

Pays d'origine autorisés : l'agrément de la BCC couvre les envois depuis la RD Congo, seule proposée par défaut (default). Le téléphone doit être un numéro du pays de résidence (callingCode). Public.

Authentification : Aucune (route publique)

Exemple de code

curl "https://sandbox.api.linc.cd/v1/origin-countries"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/origin-countries');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/origin-countries",
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/origin-countries", {
  method: "GET",
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "countries": [
    {
      "country": "CD",
      "name": "Congo-Kinshasa",
      "callingCode": "+243",
      "default": true
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Pays de résidence acceptés.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/register/resend

Renvoyer le code de vérification

Envoie un nouveau code SMS pour la vérification du téléphone.

Authentification : Aucune (route publique)

Corps de la requête

NomTypeObligatoireDescription
challengeIdstring (uuid)oui

Exemple de requête

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/register/resend" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/register/resend');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/register/resend",
    json={
        "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/register/resend", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "purpose": "phone_verification",
  "sentTo": "texte",
  "expiresAt": "2026-10-01T09:30:00Z",
  "remainingAttempts": 0
}

Réponses et erreurs

StatutSignification
201

Nouveau code envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/verify-phone

Vérifier le téléphone

Valide le code SMS, active le compte et ouvre une session mobile.

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
X-Device-Iden-têtestringnon

Identifiant d'installation de l'application. Un appareil inconnu déclenche la double authentification.

Corps de la requête

NomTypeObligatoireDescription
challengeIdstring (uuid)oui
codestringoui

Code à 6 chiffres reçu par SMS.

Exemple de requête

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/verify-phone" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/verify-phone');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/verify-phone",
    json={
        "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
        "code": "••••••"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/verify-phone", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "code": "••••••"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "tokenType": "Bearer",
  "accessToken": "…",
  "expiresIn": 0,
  "refreshToken": "…",
  "refreshExpiresIn": 0
}

Réponses et erreurs

StatutSignification
200

Téléphone vérifié. Jetons de session.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/login

Se connecter

Connexion par téléphone ou e-mail. Sur un appareil connu : jetons de session (200). Sur un nouvel appareil : double authentification requise (202), à terminer avec POST /v1/auth/login/{pendingLoginId}/verify.

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
X-Device-Iden-têtestringnon

Identifiant d'installation de l'application. Un appareil inconnu déclenche la double authentification.

Corps de la requête

NomTypeObligatoireDescription
identifierstringoui

Téléphone ou e-mail.

passwordstringoui

Exemple de requête

{
  "identifier": "+243810000000",
  "password": "••••••••"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
  "identifier": "+243810000000",
  "password": "••••••••"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/login');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "identifier": "+243810000000",
  "password": "••••••••"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/login",
    json={
        "identifier": "+243810000000",
        "password": "••••••••"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/login", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "identifier": "+243810000000",
    "password": "••••••••"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "status": "two_factor_required",
  "pendingLoginId": "0192a7c4-2c9d-7e41-a3b5-6f7e8d9c0b12",
  "methods": [
    "totp",
    "sms",
    "backup_code"
  ],
  "expiresAt": "2026-09-29T14:05:00+00:00"
}

Réponses et erreurs

StatutSignification
200

Connexion réussie.

202

Double authentification requise.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/login/{pendingLoginId}/sms

Recevoir le code de connexion par SMS

Envoie un code SMS pour terminer une connexion en attente.

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
pendingLoginIdcheminstringoui

Identifiant de la connexion en attente.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/sms"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/sms');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/sms",
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/sms", {
  method: "POST",
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "purpose": "phone_verification",
  "sentTo": "texte",
  "expiresAt": "2026-10-01T09:30:00Z",
  "remainingAttempts": 0
}

Réponses et erreurs

StatutSignification
201

Code envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/login/{pendingLoginId}/verify

Terminer la connexion avec le second facteur

Vérifie le code TOTP, SMS ou de secours et ouvre la session sur ce nouvel appareil.

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
pendingLoginIdcheminstringoui

Identifiant de la connexion en attente.

X-Device-Iden-têtestringnon

Identifiant d'installation de l'application. Un appareil inconnu déclenche la double authentification.

Corps de la requête

NomTypeObligatoireDescription
methodstringoui

totp · sms · backup_code

codestringoui
challengeIdstring (uuid)non

Exemple de requête

{
  "method": "totp",
  "code": "••••••"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify" \
  -H "Content-Type: application/json" \
  -d '{
  "method": "totp",
  "code": "••••••"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "method": "totp",
  "code": "••••••"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify",
    json={
        "method": "totp",
        "code": "••••••"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/login/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "method": "totp",
    "code": "••••••"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "tokenType": "Bearer",
  "accessToken": "eyJ…",
  "expiresIn": 900,
  "refreshToken": "…",
  "refreshExpiresIn": 2592000
}

Réponses et erreurs

StatutSignification
200

Connexion réussie.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/refresh

Renouveler les jetons

Échange le jeton de rafraîchissement contre une nouvelle paire (rotation). Un jeton réutilisé révoque la session.

Authentification : Aucune (route publique)

Corps de la requête

NomTypeObligatoireDescription
refreshTokenstringoui

Exemple de requête

{
  "refreshToken": "…"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{
  "refreshToken": "…"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/refresh');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "refreshToken": "…"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/refresh",
    json={
        "refreshToken": "…"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/refresh", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "refreshToken": "…"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "tokenType": "Bearer",
  "accessToken": "eyJ…",
  "expiresIn": 900,
  "refreshToken": "…",
  "refreshExpiresIn": 2592000
}

Réponses et erreurs

StatutSignification
200

Nouvelle paire de jetons.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/auth/logout

Se déconnecter

Révoque le jeton de rafraîchissement.

Authentification : Aucune (route publique)

Corps de la requête

NomTypeObligatoireDescription
refreshTokenstringoui

Exemple de requête

{
  "refreshToken": "…"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/auth/logout" \
  -H "Content-Type: application/json" \
  -d '{
  "refreshToken": "…"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/auth/logout');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "refreshToken": "…"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/auth/logout",
    json={
        "refreshToken": "…"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/auth/logout", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "refreshToken": "…"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Session fermée.

Réponses et erreurs

StatutSignification
204

Session fermée.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me

Afficher mon profil

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "fullName": "texte",
  "phone": "+243810000000",
  "email": "client@example.com",
  "status": "pending_verification",
  "kycLevel": 1,
  "accountMode": "wallet",
  "twoFactor": {
    "totp": true,
    "sms": true,
    "backupCodesRemaining": true
  },
  "consents": {
    "termsAcceptanceRequired": true,
    "pending": [
      {
        "document": "terms",
        "version": "texte"
      }
    ],
    "biometric": true
  }
}

Réponses et erreurs

StatutSignification
200

Profil du client connecté.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PUT /v1/me/locale

Choisir la langue du compte

Langue choisie dans le profil de l'application (fr ou en). Les e-mails et SMS sont écrits dans cette langue. Les messages d'erreur de l'API suivent l'en-tête Accept-Language.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
localestringoui

fr · en

Exemple de requête

{
  "locale": "fr"
}

Exemple de code

curl -X PUT "https://sandbox.api.linc.cd/v1/me/locale" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "locale": "fr"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/locale');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "locale": "fr"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.put(
    "https://sandbox.api.linc.cd/v1/me/locale",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "locale": "fr"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/locale", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "locale": "fr"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "locale": "fr"
}

Réponses et erreurs

StatutSignification
200

Langue enregistrée.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/consents/contract

Accepter la nouvelle version des documents du contrat

Accepte les versions actuelles des documents dont une nouvelle version attend l'acceptation (GET /v1/me, consents.pending) : une case par document en attente (Conditions générales, Politique de confidentialité, Politique LBC/FT), jamais cochée à la place du client. Le contrat d'utilisation qui les liste est accepté avec eux ; il a sa propre case (acceptContract) quand il est seul à avoir changé. Sans acceptation, le client peut lire (solde, historique) mais ne peut lancer aucune opération (403 contract_acceptance_required). Restent ouverts : la session, les appareils, le KYC, les réclamations et le retrait de ses propres fonds (POST /v1/wallet/withdrawal-codes, son annulation et le code SMS purpose: withdrawal).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
acceptTermsbooleannon

Case des Conditions générales, obligatoire si elles sont en attente.

acceptPrivacybooleannon

Case de la Politique de confidentialité, obligatoire si elle est en attente.

acceptAmlbooleannon

Case de la Politique LBC/FT, obligatoire si elle est en attente.

acceptContractbooleannon

Case du contrat d'utilisation, obligatoire seulement s'il est seul en attente.

Exemple de requête

{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/consents/contract" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/consents/contract');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/consents/contract",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "acceptTerms": False,
        "acceptPrivacy": False,
        "acceptAml": False,
        "acceptContract": False
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/consents/contract", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "acceptTerms": false,
    "acceptPrivacy": false,
    "acceptAml": false,
    "acceptContract": false
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "termsAcceptanceRequired": true,
  "pending": [
    {
      "document": "terms",
      "version": "texte"
    }
  ],
  "biometric": true
}

Réponses et erreurs

StatutSignification
200

Consentements à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/consents/terms

Accepter les documents du contrat (ancien nom)

Ancien nom de POST /v1/me/consents/contract, conservé pour les premières versions des applications : même corps, mêmes cases à cocher par le client, mêmes réponses. Sans case cochée, la réponse est 422 contract_not_accepted (le serveur n'accepte jamais à la place du client). Réponse marquée Deprecation: true.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
acceptTermsbooleannon

Case des Conditions générales, obligatoire si elles sont en attente.

acceptPrivacybooleannon

Case de la Politique de confidentialité, obligatoire si elle est en attente.

acceptAmlbooleannon

Case de la Politique LBC/FT, obligatoire si elle est en attente.

acceptContractbooleannon

Case du contrat d'utilisation, obligatoire seulement s'il est seul en attente.

Exemple de requête

{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/consents/terms" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/consents/terms');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "acceptTerms": false,
  "acceptPrivacy": false,
  "acceptAml": false,
  "acceptContract": false
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/consents/terms",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "acceptTerms": False,
        "acceptPrivacy": False,
        "acceptAml": False,
        "acceptContract": False
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/consents/terms", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "acceptTerms": false,
    "acceptPrivacy": false,
    "acceptAml": false,
    "acceptContract": false
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "termsAcceptanceRequired": true,
  "pending": [
    {
      "document": "terms",
      "version": "texte"
    }
  ],
  "biometric": true
}

Réponses et erreurs

StatutSignification
200

Consentements à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me/documents

Mes documents

Les documents du contrat d'utilisation en vigueur (Conditions générales, Politique de confidentialité, Politique LBC/FT, contrat) avec, pour chacun, la version acceptée par le client, la date et le canal, le contrat accepté avec les versions des trois documents, et les documents dont une nouvelle version attend l'acceptation (POST /v1/me/consents/contract).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me/documents" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/documents');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me/documents",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/documents", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "documents": [
    {
      "document": "terms",
      "title": "texte",
      "version": "texte",
      "draft": true,
      "accepted": {
        "version": "texte",
        "acceptedAt": "2026-10-01T09:30:00Z",
        "channel": "web",
        "agent": true
      },
      "upToDate": true
    }
  ],
  "contract": {
    "version": "texte",
    "acceptedAt": "2026-10-01T09:30:00Z",
    "channel": "web",
    "agent": true,
    "documents": {},
    "upToDate": true,
    "reference": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
  },
  "pending": [
    "terms"
  ]
}

Réponses et erreurs

StatutSignification
200

Documents et preuves d'acceptation.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PUT /v1/me/account-mode

Choisir le mode de compte

wallet conserve un solde chez Linc. pass_through débite directement le mobile money.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
modestringoui

wallet · pass_through

Exemple de requête

{
  "mode": "wallet"
}

Exemple de code

curl -X PUT "https://sandbox.api.linc.cd/v1/me/account-mode" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "wallet"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/account-mode');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "mode": "wallet"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.put(
    "https://sandbox.api.linc.cd/v1/me/account-mode",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "mode": "wallet"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/account-mode", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "mode": "wallet"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "accountMode": "wallet"
}

Réponses et erreurs

StatutSignification
200

Mode enregistré.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me/communications

Afficher les choix de communication

Nouveautés de Linc par e-mail et par SMS, envoyées seulement avec l'accord du client. Les codes, reçus et alertes de sécurité sont toujours envoyés.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me/communications" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/communications');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me/communications",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/communications", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "email": true,
  "sms": true
}

Réponses et erreurs

StatutSignification
200

Choix en cours.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PUT /v1/me/communications

Choisir les communications

Oui ou non pour chaque canal. Chaque choix est conservé comme preuve du consentement.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
emailbooleanoui

Nouveautés par e-mail (à une adresse vérifiée seulement).

smsbooleanoui

Nouveautés par SMS, de 8 h à 20 h (heure de Kinshasa). Répondre STOP les arrête.

Exemple de requête

{
  "email": true,
  "sms": true
}

Exemple de code

curl -X PUT "https://sandbox.api.linc.cd/v1/me/communications" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": true,
  "sms": true
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/communications');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "email": true,
  "sms": true
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.put(
    "https://sandbox.api.linc.cd/v1/me/communications",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "email": True,
        "sms": True
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/communications", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "email": true,
    "sms": true
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "email": true,
  "sms": true
}

Réponses et erreurs

StatutSignification
200

Choix enregistrés.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me/security/two-factor

Afficher l'état de la double authentification

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me/security/two-factor" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/two-factor');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me/security/two-factor",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/two-factor", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "totp": true,
  "sms": true,
  "backupCodesRemaining": true,
  "availableMethods": [
    "totp"
  ]
}

Réponses et erreurs

StatutSignification
200

Méthodes actives et méthodes utilisables.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/otp

Recevoir un code SMS de confirmation

Envoie un code SMS pour confirmer une opération sensible. Utilisez le challengeId retourné dans twoFactor.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
purposestringoui

security_change · transfer · payment · withdrawal · card_reveal · card_management · card_add · beneficiary_add

Exemple de requête

{
  "purpose": "security_change"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/otp" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "purpose": "security_change"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/otp');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "purpose": "security_change"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/otp",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "purpose": "security_change"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/otp", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "purpose": "security_change"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "purpose": "phone_verification",
  "sentTo": "texte",
  "expiresAt": "2026-10-01T09:30:00Z",
  "remainingAttempts": 0
}

Réponses et erreurs

StatutSignification
201

Code envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/password

Changer le mot de passe

Exige le mot de passe actuel et un second facteur. Les autres sessions sont fermées.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
currentPasswordstringoui
newPasswordstringoui
twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "currentPassword": "••••••••",
  "newPassword": "••••••••",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/password" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "currentPassword": "••••••••",
  "newPassword": "••••••••",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/password');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "currentPassword": "••••••••",
  "newPassword": "••••••••",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/password",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "currentPassword": "••••••••",
        "newPassword": "••••••••",
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/password", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "currentPassword": "••••••••",
    "newPassword": "••••••••",
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Mot de passe changé.

Réponses et erreurs

StatutSignification
204

Mot de passe changé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/totp/setup

Commencer l'activation TOTP

Retourne le secret et l'URI otpauth:// à afficher en QR code. Second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/totp/setup" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/totp/setup');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/totp/setup",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/totp/setup", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "secret": "••••••••",
  "uri": "texte"
}

Réponses et erreurs

StatutSignification
201

Secret généré, en attente de confirmation.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/totp/confirm

Confirmer l'activation TOTP

Valide un premier code de l'application. Retourne les codes de secours, affichés une seule fois.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
codestringoui

Code à 6 chiffres de l'application d'authentification.

Exemple de requête

{
  "code": "••••••"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/totp/confirm" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "••••••"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/totp/confirm');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "code": "••••••"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/totp/confirm",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "code": "••••••"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/totp/confirm", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "code": "••••••"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "backupCodes": [
    "123456"
  ]
}

Réponses et erreurs

StatutSignification
200

TOTP activé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/totp/disable

Désactiver TOTP

Second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/totp/disable" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/totp/disable');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/totp/disable",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/totp/disable", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

TOTP désactivé.

Réponses et erreurs

StatutSignification
204

TOTP désactivé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PUT /v1/me/security/sms

Activer ou désactiver la double authentification par SMS

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
enabledbooleanoui
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "enabled": true
}

Exemple de code

curl -X PUT "https://sandbox.api.linc.cd/v1/me/security/sms" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/sms');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "enabled": true
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.put(
    "https://sandbox.api.linc.cd/v1/me/security/sms",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "enabled": True
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/sms", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "enabled": true
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "totp": true,
  "sms": true,
  "backupCodesRemaining": true
}

Réponses et erreurs

StatutSignification
200

Nouvel état de la double authentification.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/me/security/backup-codes

Régénérer les codes de secours

Invalide les anciens codes. TOTP actif et second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/me/security/backup-codes" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/security/backup-codes');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/me/security/backup-codes",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/security/backup-codes", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "backupCodes": [
    "123456"
  ]
}

Réponses et erreurs

StatutSignification
200

Nouveaux codes, affichés une seule fois.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/kyc/cases

Ouvrir un dossier KYC

Ouvre un dossier pour le niveau 2 (identité vérifiée) ou 3 (vigilance renforcée).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Corps de la requête

NomTypeObligatoireDescription
targetLevelintegeroui

2 · 3

documentTypestringnon

voter_card · passport · driving_license · national_id

documentNumberstringnon
issuingCountrystringnon
residenceCountrystringnon

Pays de résidence (ISO 3166 alpha-2), niveau 2. Une fois le dossier approuvé, il remplace l'indicatif du téléphone pour les services ouverts par pays.

birthDatestring (date)non
addressstringnon
occupationstringnon
sourceOfFundsstringnon
expectedMonthlyAmountstringnon

Montant mensuel attendu en USD (décimal en texte), par exemple 1500.00.

documentExpiresOnstring (date)non

Date d'expiration imprimée sur la pièce (niveau 2). Aucune lecture automatique en mode manual_review ; une pièce expirée est refusée.

nationalitystringnon

Nationalité (ISO 3166 alpha-2), niveau 2. Par défaut, le pays qui a délivré la pièce.

residencePermitNumberstringnon

Numéro du titre de séjour (carte de résident). Exigé quand la nationalité ou la pièce n'est pas celle du pays de résidence (étranger résidant) : requiredDocuments comprend alors son recto et son verso, et la conformité vérifie le dossier.

residencePermitExpiresOnstring (date)non

Date d'expiration du titre de séjour ; son renouvellement suit celui de la pièce.

Exemple de requête

{
  "targetLevel": 2
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/kyc/cases" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "targetLevel": 2
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/kyc/cases');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "targetLevel": 2
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/kyc/cases",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "targetLevel": 2
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/kyc/cases", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "targetLevel": 2
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "reference": "LP-7K2Q4F",
  "targetLevel": 2,
  "status": "draft",
  "message": "texte",
  "requiredDocuments": [
    "id_front"
  ],
  "optionalDocuments": [
    "id_front"
  ],
  "uploadedDocuments": [
    "id_front"
  ],
  "livenessChallenges": [
    {
      "code": "turn_left",
      "instruction": "texte"
    }
  ],
  "captureSteps": [
    {
      "kind": "id_front",
      "challenge": "turn_left",
      "label": "texte",
      "done": true
    }
  ],
  "documentExpiresOn": "1990-01-31",
  "reviewHours": 0,
  "submittedAt": "2026-10-01T09:30:00Z",
  "decidedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
201

Dossier ouvert.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/kyc/cases/current

Afficher mon dossier KYC en cours

Niveau actuel et dernier dossier. Interrogez cette route pour suivre la décision.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/kyc/cases/current" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/kyc/cases/current');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/kyc/cases/current",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/kyc/cases/current", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "kycLevel": 1,
  "case": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "reference": "LP-7K2Q4F",
    "targetLevel": 2,
    "status": "draft",
    "message": "texte",
    "requiredDocuments": [
      "id_front"
    ],
    "optionalDocuments": [
      "id_front"
    ],
    "uploadedDocuments": [
      "id_front"
    ],
    "livenessChallenges": [
      {
        "code": "turn_left",
        "instruction": "texte"
      }
    ],
    "captureSteps": [
      {
        "kind": "id_front",
        "challenge": "turn_left",
        "label": "texte",
        "done": true
      }
    ],
    "documentExpiresOn": "1990-01-31",
    "reviewHours": 0,
    "submittedAt": "2026-10-01T09:30:00Z",
    "decidedAt": "2026-10-01T09:30:00Z"
  }
}

Réponses et erreurs

StatutSignification
200

Niveau KYC et dossier (ou null).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/kyc/cases/{id}/documents/{kind}

Ajouter un document au dossier KYC

Envoie une photo dans le champ multipart file (capture guidée). Au niveau 2, la pièce et le visage viennent de la caméra (captureSource=camera) : un fichier choisi est refusé (kyc_camera_required). Chaque image du vivant indique sa consigne (challenge). Taille minimale (côté long) : 1000 px pour la pièce, 480 px pour le visage (kyc_image_too_small). Le selfie et les images du vivant exigent le consentement biométrique.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du dossier.

kindcheminstringoui

Type de document.

Corps de la requête

Fichier envoyé en multipart/form-data.

NomTypeObligatoireDescription
filestringoui

Photo du document (JPEG, PNG ou PDF).

captureSourcestringnon

Origine de l'image ; camera obligatoire pour la pièce et le visage au niveau 2.

camera · handoff · upload

challengestringnon

Consigne du contrôle du vivant actif.

turn_left · turn_right · blink · smile · look_up

brightnessintegernon

Luminosité moyenne mesurée par l'application avant l'envoi.

sharpnessintegernon

Netteté mesurée par l'application (variance du laplacien).

glareintegernon

Part de pixels brûlés (reflet), en millièmes.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/documents/id_front" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -F "file=@document.jpg"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/documents/id_front');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_POSTFIELDS => ['file' => new CURLFile('document.jpg')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/documents/id_front",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    files={"file": open("document.jpg", "rb")},
    timeout=30,
)
print(answer.status_code, answer.text)
import { openAsBlob } from "node:fs";

const form = new FormData();
form.append("file", await openAsBlob("document.jpg"), "document.jpg");

const answer = await fetch("https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/documents/id_front", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
  body: form,
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "document": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "kind": "id_front",
    "size": 0
  },
  "case": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "reference": "LP-7K2Q4F",
    "targetLevel": 2,
    "status": "draft",
    "message": "texte",
    "requiredDocuments": [
      "id_front"
    ],
    "optionalDocuments": [
      "id_front"
    ],
    "uploadedDocuments": [
      "id_front"
    ],
    "livenessChallenges": [
      {
        "code": "turn_left",
        "instruction": "texte"
      }
    ],
    "captureSteps": [
      {
        "kind": "id_front",
        "challenge": "turn_left",
        "label": "texte",
        "done": true
      }
    ],
    "documentExpiresOn": "1990-01-31",
    "reviewHours": 0,
    "submittedAt": "2026-10-01T09:30:00Z",
    "decidedAt": "2026-10-01T09:30:00Z"
  }
}

Réponses et erreurs

StatutSignification
201

Document ajouté.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/kyc/cases/{id}/submit

Envoyer le dossier KYC

Lance la vérification. Le résultat arrive de façon asynchrone (SMS et GET /v1/kyc/cases/current).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du dossier.

Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/submit" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/submit');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16))],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/submit",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/kyc/cases/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/submit", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID() },
});
console.log(answer.status, await answer.text());

Exemple de réponse 202

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "reference": "LP-7K2Q4F",
  "targetLevel": 2,
  "status": "draft",
  "message": "texte",
  "requiredDocuments": [
    "id_front"
  ],
  "optionalDocuments": [
    "id_front"
  ],
  "uploadedDocuments": [
    "id_front"
  ],
  "livenessChallenges": [
    {
      "code": "turn_left",
      "instruction": "texte"
    }
  ],
  "captureSteps": [
    {
      "kind": "id_front",
      "challenge": "turn_left",
      "label": "texte",
      "done": true
    }
  ],
  "documentExpiresOn": "1990-01-31",
  "reviewHours": 0,
  "submittedAt": "2026-10-01T09:30:00Z",
  "decidedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
202

Dossier envoyé, vérification en cours.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/corridors

Lister les corridors ouverts

Pays de destination, devises et modes de réception ouverts (public). Un pays fermé, ou dont tous les corridors sont fermés, n'apparaît pas ; un corridor fermé (mode de réception d'un pays) n'est pas dans payoutMethods (« Partenaires › Pays et corridors », docs/adr/0068). Les devis suivent aussitôt.

Authentification : Aucune (route publique)

Exemple de code

curl "https://sandbox.api.linc.cd/v1/corridors"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/corridors');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/corridors",
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/corridors", {
  method: "GET",
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "corridors": [
    {
      "country": "CI",
      "name": "Côte d’Ivoire",
      "currency": "XOF",
      "currencies": [
        "XOF"
      ],
      "payoutMethods": [
        "mobile_money",
        "bank_account",
        "card"
      ]
    },
    {
      "country": "CA",
      "name": "Canada",
      "currency": "CAD",
      "currencies": [
        "CAD",
        "USD"
      ],
      "payoutMethods": [
        "bank_account",
        "card"
      ]
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Corridors ouverts.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/journeys

Lister les parcours ouverts pour le client

Parcours de paiement (source → destination) ouverts pour le client authentifié vers un pays, et une devise de réception si elle est donnée (« Partenaires › Parcours », docs/adr/0083). Seuls ces parcours sont à proposer : ils tiennent compte de l'état du parcours, du pays, du niveau KYC, de la population (liste pilote, segment) et du mode de compte. Les autres verrous (corridors, partenaires) restent ceux de listCorridors et du devis ; chaque devis, envoi et paiement revérifie le parcours et refuse sinon avec operation_unavailable.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
countryrequêtestringoui

Pays de destination (le pays du marchand pour un paiement, CD pour le solde).

currencyrequêtestringnon

Devise reçue ; absente, toute devise.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/journeys?country=KE" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/journeys?country=KE');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/journeys?country=KE",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/journeys?country=KE", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "country": "KE",
  "currency": "USD",
  "journeys": [
    {
      "source": "card_visa_aft",
      "destination": "card_visa"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Parcours ouverts pour ce client.

422

journey_query_invalid : country n'est pas un code pays ISO à deux lettres, ou currency n'est pas une devise connue de Linc.

Erreur au format application/problem+json : voir « Erreurs ».

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/quotes

Demander un devis

Frais, taux, total débité et montant reçu, verrouillés 60 s. Au plus 20 devis par minute et par client (renouvellements compris) : au-delà, 429 too_many_quotes.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Corps de la requête

NomTypeObligatoireDescription
amountstringnon

Montant envoyé en décimal (texte), par exemple 150.00. Ancien nom de sendAmount.

sendAmountstringnon

Montant envoyé en décimal (texte), par exemple 150.00.

receiveAmountstringnon

Montant à recevoir dans la devise reçue, avec ses décimales (XOF 0, KWD 3), par exemple 50000.

totalAmountstringnon

Total payé par le client dans la devise envoyée, frais déduits, par exemple 100.00.

operatorstringnon

Facultatif (mobile_money) : opérateur du wallet du bénéficiaire, son nom ou son code (operators de GET /v1/reference/destination-formats). La ligne de la grille du partenaire pour cet opérateur s'applique au devis. Inconnu : ignoré.

msisdnstringnon

Facultatif (mobile_money) : numéro du bénéficiaire, l'opérateur est déduit de son préfixe quand operator est absent.

currencystringoui

Code devise ISO 4217.

destinationCountrystringoui
payoutMethodstringoui

cash_pickup : retrait d'espèces avec un code dans le réseau Mastercard, là où il est ouvert (bénéficiaire : nom exactement comme sur sa pièce et téléphone).

mobile_money · bank_account · card · cash_pickup

receiveCurrencystringnon

Une des devises du corridor. Vide = devise principale du corridor.

sourceTypestringnon

Source des fonds. card (carte bancaire, AFT) a ses propres frais ; le devis ne sert alors qu'à un envoi par carte. card_interswitch : carte sur la page de paiement Interswitch, frais propres, parcours fermé par défaut.

· mobile_money · wallet · card · card_interswitch

Exemple de requête

{
  "amount": "150.00",
  "currency": "USD",
  "destinationCountry": "CI",
  "payoutMethod": "mobile_money",
  "sourceType": "mobile_money"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/quotes" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": "150.00",
  "currency": "USD",
  "destinationCountry": "CI",
  "payoutMethod": "mobile_money",
  "sourceType": "mobile_money"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/quotes');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "amount": "150.00",
  "currency": "USD",
  "destinationCountry": "CI",
  "payoutMethod": "mobile_money",
  "sourceType": "mobile_money"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/quotes",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "amount": "150.00",
        "currency": "USD",
        "destinationCountry": "CI",
        "payoutMethod": "mobile_money",
        "sourceType": "mobile_money"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/quotes", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "amount": "150.00",
    "currency": "USD",
    "destinationCountry": "CI",
    "payoutMethod": "mobile_money",
    "sourceType": "mobile_money"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
  "send": {
    "amount": 15000,
    "currency": "USD",
    "display": "150,00 $"
  },
  "fee": {
    "amount": 325,
    "currency": "USD",
    "display": "3,25 $"
  },
  "vat": {
    "amount": 52,
    "currency": "USD",
    "display": "0,52 $"
  },
  "levy": {
    "amount": 30,
    "currency": "USD",
    "display": "0,30 $"
  },
  "total": {
    "amount": 15407,
    "currency": "USD",
    "display": "154,07 $"
  },
  "receive": {
    "amount": 84900,
    "currency": "XOF",
    "display": "84 900 FCFA"
  },
  "rate": "566.00",
  "destinationCountry": "CI",
  "payoutMethod": "mobile_money",
  "createdAt": "2026-09-29T14:00:00+00:00",
  "expiresAt": "2026-09-29T14:01:00+00:00",
  "consumed": false,
  "sourceType": null
}

Réponses et erreurs

StatutSignification
201

Devis créé.

422

Refus métier (Problem.code), dont journey_limit_exceeded : le montant dépasse un plafond du parcours de paiement (par envoi, par jour ou par mois, en USD quelle que soit la devise envoyée, docs/adr/0083). detail donne le plafond atteint (« 30.00 USD »). Un parcours fermé répond operation_unavailable (403), sans motif.

Erreur au format application/problem+json : voir « Erreurs ».

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/quotes/preview

Aperçu du prix pendant la saisie

Prix indicatif dans tous les sens : sendAmount (ou amount), receiveAmount ou totalAmount (« frais déduits », là où le corridor l'offre) — deux ou aucun → 422 amount_ambiguous. Un total qui ne couvre pas les frais → 422 total_below_fees ; un prix à perte → 422 margin_too_low. Rien n'est enregistré, aucun taux n'est verrouillé ; les plafonds du client sont vérifiés pour le dire tout de suite. Le devis (POST /v1/quotes) est demandé quand le client continue. Plus de 12 chiffres avant la virgule, ou un montant trop grand pour être calculé → 422 amount_too_large.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
destinationCountryrequêtestringoui
payoutMethodrequêtestringoui
currencyrequêtestringnon

Devise envoyée (USD par défaut).

sendAmountrequêtestringnon
amountrequêtestringnon

Ancien nom de sendAmount.

receiveAmountrequêtestringnon
totalAmountrequêtestringnon

Total payé par le client dans la devise envoyée

receiveCurrencyrequêtestringnon
sourceTyperequêtestringnon
operatorrequêtestringnon

Opérateur du wallet du bénéficiaire (nom ou code), pour sa ligne de la grille du partenaire.

msisdnrequêtestringnon

Numéro du bénéficiaire : opérateur déduit du préfixe sans operator.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/quotes/preview?destinationCountry=KE&payoutMethod=mobile_money" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/quotes/preview?destinationCountry=KE&payoutMethod=mobile_money');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/quotes/preview?destinationCountry=KE&payoutMethod=mobile_money",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/quotes/preview?destinationCountry=KE&payoutMethod=mobile_money", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "typed": "send",
  "send": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "fee": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "vat": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "levy": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "total": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "receive": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "rate": "texte"
}

Réponses et erreurs

StatutSignification
200

Prix indicatif.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/quotes/{id}

Afficher un devis

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du devis.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/quotes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/quotes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/quotes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/quotes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "send": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "fee": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "vat": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "levy": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "total": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "receive": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "rate": "texte",
  "destinationCountry": "KE",
  "payoutMethod": "mobile_money",
  "createdAt": "2026-10-01T09:30:00Z",
  "expiresAt": "2026-10-01T09:30:00Z",
  "consumed": true,
  "sourceType": "card"
}

Réponses et erreurs

StatutSignification
200

Devis.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/reference/banks

Chercher une banque du pays pendant la frappe

Banques du référentiel du pays, cherchées par nom, sigle, BIC ou code national (sort code, code banque) ; au plus 20, une par banque, à partir de 2 caractères (liste vide avant). « Autre banque » reste possible : nom et BIC saisis. Public, limité par adresse (429 au-delà).

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
countryrequêtestringoui

Pays de la banque (ISO 3166-1 alpha-2).

qrequêtestringnon

Début ou partie du nom, du sigle, du BIC ou du code de la banque ; 2 caractères au moins.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/reference/banks?country=KE"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/reference/banks?country=KE');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/reference/banks?country=KE",
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/reference/banks?country=KE", {
  method: "GET",
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "banks": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "name": "texte"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Banques trouvées (vide pour un pays inconnu).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/reference/destination-formats

Formats de destination d'un pays

Opérateurs de mobile money avec les préfixes et longueurs de leurs numéros (l'opérateur est détecté d'après le numéro : un seul possible → présélectionné, plusieurs → proposés en premier, aucun → message) et longueur de l'IBAN du pays (registre officiel) pour dire exactement ce qui manque, et schémas de compte du pays (IBAN, RIB, sort code…, le schéma par défaut en premier) avec leurs champs : l'application affiche les champs du schéma choisi et envoie scheme avec eux. Le serveur revérifie tout à l'enregistrement du bénéficiaire. Public, limité par adresse (429 au-delà).

Authentification : Aucune (route publique)

Paramètres

NomOùTypeObligatoireDescription
countryrequêtestringoui

Pays du bénéficiaire (ISO 3166-1 alpha-2).

Exemple de code

curl "https://sandbox.api.linc.cd/v1/reference/destination-formats?country=KE"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/reference/destination-formats?country=KE');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/reference/destination-formats?country=KE",
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/reference/destination-formats?country=KE", {
  method: "GET",
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "country": "KE",
  "name": "texte",
  "operators": [
    {
      "code": "mpesa",
      "name": "M-Pesa",
      "prefixes": [
        "texte"
      ],
      "lengths": [
        0
      ]
    }
  ],
  "accountSchemes": [
    {
      "code": "rib",
      "label": "RIB (UEMOA)",
      "fields": [
        {
          "detail": "accountNumber",
          "label": "texte",
          "required": true,
          "maxLength": 0,
          "numeric": true,
          "iban": true,
          "choices": []
        }
      ]
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Formats du pays (listes vides pour un pays inconnu).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/beneficiaries

Lister mes bénéficiaires

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/beneficiaries" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/beneficiaries');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/beneficiaries",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/beneficiaries", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "beneficiaries": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "fullName": "texte",
      "country": "KE",
      "payoutMethod": "mobile_money",
      "destination": "texte"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Bénéficiaires enregistrés.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/beneficiaries

Ajouter un bénéficiaire

Les coordonnées complètes restent chez Linc. La réponse les affiche masquées. Selon les contrôles de sécurité de l'opération, la réponse peut être two_factor_required : redemandez avec twoFactor (code de l'application d'authentification, ou code SMS obtenu par POST /v1/me/security/otp avec purpose = beneficiary_add). Une opération qui ne peut pas aboutir répond operation_unavailable (403), sans motif : ce code est commun à plusieurs refus.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
fullNamestringoui
countrystringoui
payoutMethodstringoui

cash_pickup : retrait d'espèces avec un code dans le réseau Mastercard, là où il est ouvert (bénéficiaire : nom exactement comme sur sa pièce et téléphone).

mobile_money · bank_account · card · cash_pickup

detailsobjectnon

Coordonnées selon le mode (msisdn, provider, bankName, accountNumber, bankCode, cardToken…). Compte bancaire : de préférence scheme (code d'un schéma de GET /v1/reference/destination-formats) et les champs de ce schéma (accountNumber pour un RIB, bankCode + accountNumber pour un sort code…), bankId d'une banque de la liste ; sans scheme, iban ou accountNumber comme avant. bankCode (compte bancaire, facultatif) : sort code (Royaume-Uni, 6 chiffres), ABA (États-Unis, 9 chiffres) ou code banque ou guichet (3 à 15 lettres ou chiffres) ; espaces et tirets ignorés. Facultatif pour tous les modes : relationship (lien avec l'expéditeur : family, friend, self, business, other), exigé par certains corridors.

twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "fullName": "Bastian Kelyan",
  "country": "CI",
  "payoutMethod": "mobile_money",
  "details": {
    "msisdn": "+2250700000000",
    "provider": "orange",
    "relationship": "family"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/beneficiaries" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "fullName": "Bastian Kelyan",
  "country": "CI",
  "payoutMethod": "mobile_money",
  "details": {
    "msisdn": "+2250700000000",
    "provider": "orange",
    "relationship": "family"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/beneficiaries');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "fullName": "Bastian Kelyan",
  "country": "CI",
  "payoutMethod": "mobile_money",
  "details": {
    "msisdn": "+2250700000000",
    "provider": "orange",
    "relationship": "family"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/beneficiaries",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "fullName": "Bastian Kelyan",
        "country": "CI",
        "payoutMethod": "mobile_money",
        "details": {
            "msisdn": "+2250700000000",
            "provider": "orange",
            "relationship": "family"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/beneficiaries", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "fullName": "Bastian Kelyan",
    "country": "CI",
    "payoutMethod": "mobile_money",
    "details": {
      "msisdn": "+2250700000000",
      "provider": "orange",
      "relationship": "family"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
  "fullName": "Bastian Kelyan",
  "country": "CI",
  "payoutMethod": "mobile_money",
  "destination": "Orange Money •• 0000"
}

Réponses et erreurs

StatutSignification
201

Bénéficiaire ajouté.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PATCH /v1/beneficiaries/{id}

Compléter le code banque d'un bénéficiaire

Ajoute le code banque (bankCode) d'un bénéficiaire à compte bancaire enregistré sans lui, quand l'envoi répond corridor_fields_missing avec bank_code. Contrôle selon le pays : sort code au Royaume-Uni (6 chiffres), ABA aux États-Unis (9 chiffres), 3 à 15 lettres ou chiffres ailleurs ; espaces et tirets ignorés. Un code déjà enregistré n'est jamais remplacé (beneficiary_bank_code_set, 409 : une autre banque est un autre bénéficiaire) ; le même code ne change rien. Contrôles de sécurité de l'ajout d'un bénéficiaire : la réponse peut être two_factor_required, redemandez avec twoFactor (purpose = beneficiary_add).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du bénéficiaire.

Corps de la requête

NomTypeObligatoireDescription
bankCodestringoui

Sort code (Royaume-Uni), ABA (États-Unis) ou code banque ou guichet.

twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "bankCode": "123456"
}

Exemple de code

curl -X PATCH "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "bankCode": "123456"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "bankCode": "123456"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.patch(
    "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "bankCode": "123456"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "bankCode": "123456"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "fullName": "texte",
  "country": "KE",
  "payoutMethod": "mobile_money",
  "destination": "texte"
}

Réponses et erreurs

StatutSignification
200

Bénéficiaire complété (coordonnées masquées).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

DELETE /v1/beneficiaries/{id}

Supprimer un bénéficiaire

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du bénéficiaire.

Exemple de code

curl -X DELETE "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.delete(
    "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Bénéficiaire supprimé.

Réponses et erreurs

StatutSignification
204

Bénéficiaire supprimé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/beneficiaries/{id}/purposes

Motifs d'envoi proposés pour ce bénéficiaire

Motifs que le corridor accepte : sur Visa Direct et Mastercard Cross-Border, seuls ceux qui ont un code partenaire pour le pays (rail principal, ou secours s'il prend le relais) ; tous sur les autres rails. Liste vide : ne demandez pas de motif. Avec quoteId, la devise reçue du devis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant du bénéficiaire.

quoteIdrequêtestringnon

Devis en cours (devise reçue). Par défaut, la devise principale du corridor.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/purposes" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/purposes');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/purposes",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/beneficiaries/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/purposes", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "purposes": [
    {
      "code": "family_support",
      "label": "texte"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Motifs proposés, dans l'ordre d'affichage.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/transfers

Lister mes envois

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/transfers" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/transfers",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "transfers": [
    {
      "reference": "LP-7K2Q4F",
      "status": "in_progress",
      "steps": [
        {
          "label": "texte",
          "done": true
        }
      ],
      "beneficiary": "texte",
      "destination": "texte",
      "country": "KE",
      "source": "texte",
      "sourceType": "mobile_money",
      "send": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "fee": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "vat": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "levy": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "total": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "receive": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "rate": "texte",
      "createdAt": "2026-10-01T09:30:00Z",
      "deliveredAt": "2026-10-01T09:30:00Z",
      "refundedAt": "2026-10-01T09:30:00Z"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Envois du client, du plus récent au plus ancien.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers

Envoyer de l'argent

Confirme un devis vers un bénéficiaire. Second facteur requis. Le traitement est asynchrone (suivez les étapes). Un client dont le pays de résidence n'est pas un pays d'origine autorisé est refusé (origin_not_allowed, 403) avant tout prélèvement ; la conformité est alertée.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
quoteIdstring (uuid)oui
beneficiaryIdstring (uuid)oui
sourceobjectoui
source.typestringoui

wallet : mode wallet uniquement. card : carte bancaire du client (KYC niveau 2), payée ensuite sur la page carte (GET /v1/transfers/{reference}/card-checkout) avec 3-D Secure ; le devis doit être un devis carte. card_interswitch : carte (ou mobile money) payée sur la page d'Interswitch (Web Checkout), option fermée par défaut et ouverte parcours par parcours ; KYC niveau 2, devis sourceType=card_interswitch, puis GET /v1/transfers/{reference}/checkout.

mobile_money · wallet · card · card_interswitch

source.providerstringnon

airtel · mpesa · orange · afrimoney

source.msisdnstringnon
source.savedWalletIdstring (uuid)non

Source mobile_money : porte-monnaie enregistré vérifié (GET /v1/saved-wallets) ; opérateur et numéro en sont lus, provider et msisdn sont ignorés. Refusé (saved_wallet_not_verified, saved_wallet_not_found) s'il n'est pas au client ou pas vérifié.

source.savedCardIdstring (uuid)non

Source card : carte enregistrée choisie dans le devis (GET /v1/saved-cards), proposée sur la page carte sans ressaisie.

purposestringnon

Motif de l'envoi déclaré par le client, parmi ceux de GET /v1/beneficiaries/{id}/purposes (sinon transfer_purpose_not_offered). Facultatif quand la liste est vide ; un corridor qui exige un motif refuse la création sans lui (corridor_fields_missing).

family_support · education · medical · gift · savings · bills · business · salary · goods_services · other

twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "quoteId": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
  "beneficiaryId": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "purpose": "family_support",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "quoteId": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
  "beneficiaryId": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "purpose": "family_support",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "quoteId": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
  "beneficiaryId": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "purpose": "family_support",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "quoteId": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
        "beneficiaryId": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
        "source": {
            "type": "mobile_money",
            "provider": "airtel",
            "msisdn": "+243970000000"
        },
        "purpose": "family_support",
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "quoteId": "0192a7c4-5b1e-7c3a-9f10-3d2e8b6a4c11",
    "beneficiaryId": "0192a7c4-6f02-7a55-8e21-7b4c0d9e2f33",
    "source": {
      "type": "mobile_money",
      "provider": "airtel",
      "msisdn": "+243970000000"
    },
    "purpose": "family_support",
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 202

{
  "reference": "LP-8QK2ZD",
  "status": "in_progress",
  "steps": [
    {
      "label": "Envoi initié",
      "done": true
    },
    {
      "label": "Fonds prélevés sur votre mobile money",
      "done": false
    },
    {
      "label": "Versement au bénéficiaire en cours",
      "done": false
    },
    {
      "label": "Fonds reçus par le bénéficiaire",
      "done": false
    }
  ],
  "beneficiary": "Bastian Kelyan",
  "destination": "Orange Money •• 0000",
  "country": "CI",
  "source": "Airtel Money •• 0000",
  "sourceType": "mobile_money",
  "send": {
    "amount": 15000,
    "currency": "USD",
    "display": "150,00 $"
  },
  "fee": {
    "amount": 325,
    "currency": "USD",
    "display": "3,25 $"
  },
  "vat": {
    "amount": 52,
    "currency": "USD",
    "display": "0,52 $"
  },
  "levy": {
    "amount": 30,
    "currency": "USD",
    "display": "0,30 $"
  },
  "total": {
    "amount": 15407,
    "currency": "USD",
    "display": "154,07 $"
  },
  "receive": {
    "amount": 84900,
    "currency": "XOF",
    "display": "84 900 FCFA"
  },
  "rate": "566.00",
  "createdAt": "2026-09-29T14:00:20+00:00",
  "deliveredAt": null,
  "refundedAt": null
}

Réponses et erreurs

StatutSignification
202

Envoi accepté, en cours de traitement.

422

Refus métier (Problem.code), dont journey_limit_exceeded : le montant dépasse un plafond du parcours de paiement (par envoi, par jour ou par mois, en USD quelle que soit la devise envoyée, docs/adr/0083). detail donne le plafond atteint (« 30.00 USD »). Un parcours fermé répond operation_unavailable (403), sans motif.

Erreur au format application/problem+json : voir « Erreurs ».

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/transfers/{reference}/repeat

Renvoyer un transfert (valeurs pré-remplies)

« Renvoyer » : bénéficiaire, moyen de paiement, destination et montant d'un transfert terminé (livré, remboursé ou échoué), pour remplir l'écran d'envoi. Aucune écriture : l'envoi demande un nouveau devis (jamais l'ancien taux), puis suit le parcours normal (2FA, nouvelle clé d'idempotence, filtrage AML, plafonds, parcours ouvert). Bénéficiaire supprimé, corridor ou parcours fermé : complete à faux, beneficiaryId nul et issue dit quoi choisir. Transfert en cours (y compris un remboursement pas encore terminé) : 409 transfer_in_progress ; référence d'un autre client : 404 transfer_not_found. Le solde n'est repris que si le compte est en mode wallet, le motif que s'il est encore proposé pour ce bénéficiaire.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Exemple de code

curl "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/repeat" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/repeat');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/repeat",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/repeat", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "beneficiaryId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "beneficiaryName": "texte",
  "country": "KE",
  "payoutMethod": "mobile_money",
  "sendAmount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "receiveCurrency": "USD",
  "complete": true,
  "issue": {
    "code": "beneficiary_deleted",
    "message": "texte"
  }
}

Réponses et erreurs

StatutSignification
200

Valeurs de l'écran d'envoi.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/transfers/{reference}

Suivre un envoi

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "status": "in_progress",
  "steps": [
    {
      "label": "texte",
      "done": true
    }
  ],
  "beneficiary": "texte",
  "destination": "texte",
  "country": "KE",
  "source": "texte",
  "sourceType": "mobile_money",
  "send": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "fee": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "vat": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "levy": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "total": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "receive": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "rate": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "deliveredAt": "2026-10-01T09:30:00Z",
  "refundedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Envoi et étapes de suivi.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers/{reference}/cash-pickup/code

Afficher le code de retrait

Retrait d'espèces : le code à donner au bénéficiaire, après un second facteur ; jamais mis en cache, jamais renvoyé par le support. 409 cash_pickup_not_pending une fois retiré, annulé ou remboursé.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/code" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/code');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/code",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/code", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "code": "••••••"
}

Réponses et erreurs

StatutSignification
200

Code de retrait.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers/{reference}/cash-pickup/sms

Renvoyer le code au bénéficiaire par SMS

Au plus 3 renvois par envoi (429 cash_pickup_resend_limit au-delà) ; chaque envoi est journalisé.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/sms" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/sms');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/sms",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/sms", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "sent": true,
  "cashPickup": {
    "status": "pending",
    "expiresAt": "2026-10-01T09:30:00Z",
    "smsUndelivered": true,
    "resendsLeft": 0,
    "amendmentsLeft": 0,
    "nameUnderReview": true,
    "cancelledBy": "expired",
    "refundable": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "refundIfCancelled": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    }
  }
}

Réponses et erreurs

StatutSignification
200

SMS parti ou non (sent) et état du retrait.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers/{reference}/cash-pickup/cancel

Annuler un retrait d'espèces

Tant que l'argent n'est pas retiré, après un second facteur : Mastercard annule le paiement, puis le montant envoyé est remboursé (frais et marge de change conservés). 409 cash_pickup_cancel_refused si l'argent est déjà retiré : rien n'est remboursé.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/cancel" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/cancel');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/cancel",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/cancel", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "outcome": "cancelled",
  "transfer": {
    "reference": "LP-7K2Q4F",
    "status": "in_progress",
    "steps": [
      {
        "label": "texte",
        "done": true
      }
    ],
    "beneficiary": "texte",
    "destination": "texte",
    "country": "KE",
    "source": "texte",
    "sourceType": "mobile_money",
    "send": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "fee": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "vat": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "levy": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "total": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "receive": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "rate": "texte",
    "createdAt": "2026-10-01T09:30:00Z",
    "deliveredAt": "2026-10-01T09:30:00Z",
    "refundedAt": "2026-10-01T09:30:00Z"
  }
}

Réponses et erreurs

StatutSignification
200

Issue de l'annulation et envoi à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers/{reference}/cash-pickup/name

Corriger le nom du bénéficiaire d'un retrait

Une fois par envoi, avant le retrait, après un second facteur. Une faute de frappe est corrigée chez Mastercard aussitôt (amended: true) ; au-delà, la conformité valide d'abord (amended: false). 409 cash_pickup_amend_limit, 409 cash_pickup_amend_refused (refusée par Mastercard), 503 cash_pickup_amend_unknown (Mastercard n'a pas répondu : le nom n'est pas modifié, les opérations vérifient).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
namestringoui

Nom complet du bénéficiaire, exactement comme sur sa pièce d'identité.

twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "name": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/name" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/name');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "name": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/name",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "name": "texte",
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/cash-pickup/name", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "texte",
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "amended": true
}

Réponses et erreurs

StatutSignification
200

Corrigé ou en attente de la conformité.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/transfers/{reference}/card-checkout

Ouvrir la page carte d'un envoi

Envoi financé par carte bancaire : page carte, ouverte une fois la vérification de l'envoi passée. Chaque appel donne un nouveau lien à usage unique. 409 card_checkout_not_ready pendant la vérification (réessayez), ou card_payment_closed une fois le paiement par carte terminé.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/card-checkout" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/card-checkout');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/card-checkout",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/card-checkout", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "url": "https://example.com",
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Page carte à ouvrir.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/transfers/{reference}/checkout

Ouvrir la page de paiement Interswitch d'un envoi

Envoi payé sur la page de paiement d'Interswitch (Web Checkout) : lien signé qui ouvre cette page dans la vue web de l'application. Le client y choisit son moyen de paiement puis revient par linc-client://envoi/retour ; la redirection ne prouve rien, suivez l'envoi avec GET /v1/transfers/{reference} (la collecte est confirmée de serveur à serveur). 409 checkout_not_ready pendant la vérification de l'envoi (réessayez), checkout_unavailable quand aucun paiement n'attend le client sur cette page (envoi payé autrement, ou déjà confirmé).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de l'envoi.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/checkout" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/checkout');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/checkout",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/checkout", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "url": "https://example.com",
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Page de paiement à ouvrir.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/card-payments/{reference}

Suivre un paiement par carte

Issue du paiement par carte d'un envoi ou d'un paiement marchand du client (après la page carte).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence du paiement par carte.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/card-payments/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/card-payments/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/card-payments/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/card-payments/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "statusLabel": "texte",
  "purpose": "merchant_payment",
  "subject": "texte",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "card": "texte",
  "message": "texte",
  "attemptsLeft": 0,
  "expiresAt": "2026-10-01T09:30:00Z",
  "approvedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Paiement par carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/saved-cards

Lister mes cartes bancaires enregistrées

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/saved-cards" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-cards');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/saved-cards",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-cards", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "cards": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "label": "texte",
      "network": "visa",
      "last4": "texte",
      "expiry": "texte",
      "issuerCountry": "KE",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "verificationHold": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "verificationNotice": "texte"
}

Réponses et erreurs

StatutSignification
200

Cartes enregistrées (réseau, 4 derniers chiffres, expiration).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/saved-cards

Ajouter une carte bancaire sans paiement

Second facteur requis (purpose card_add), KYC niveau 2. Ouvre la page carte d'une vérification (CV-XXXXXX) : la carte est saisie dans le formulaire hébergé de l'acquéreur, contrôlée comme une carte qui finance un envoi, puis vérifiée par une autorisation de 1 USD (verificationHold de GET /v1/saved-cards, paramétrable) SANS capture, avec 3-D Secure obligatoire. Dès que la banque l'accepte et authentifie le titulaire, l'autorisation est annulée et la carte enregistrée ; rien n'est prélevé. Prévenez le client avant la saisie avec verificationNotice. Suivez l'issue avec GET /v1/card-payments/{reference} (approved puis reversed, ou failed) puis GET /v1/saved-cards. La période d'observation démarre à la vérification.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/saved-cards" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-cards');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/saved-cards",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-cards", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "url": "https://example.com",
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
201

Page carte à ouvrir (lien à usage unique).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PATCH /v1/saved-cards/{id}

Nommer une carte enregistrée ou la choisir par défaut

nickname : nom donné par le client (40 caractères au plus, vide pour l'effacer) ; default : true en fait la carte proposée en premier au prochain paiement (une seule par client). Un champ absent est laissé tel quel.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte enregistrée.

Corps de la requête

NomTypeObligatoireDescription
nicknamestringnon

Nom donné à la carte ; vide pour l'effacer.

defaultbooleannon

Exemple de requête

{
  "nickname": "texte",
  "default": true
}

Exemple de code

curl -X PATCH "https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "nickname": "texte",
  "default": true
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "nickname": "texte",
  "default": true
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.patch(
    "https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "nickname": "texte",
        "default": True
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "nickname": "texte",
    "default": true
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "label": "texte",
  "network": "visa",
  "last4": "texte",
  "expiry": "texte",
  "issuerCountry": "KE",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Carte mise à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

DELETE /v1/saved-cards/{id}

Supprimer une carte bancaire enregistrée

Le jeton est aussi supprimé chez l'acquéreur.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte enregistrée.

Exemple de code

curl -X DELETE "https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.delete(
    "https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Carte supprimée.

Réponses et erreurs

StatutSignification
204

Carte supprimée.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/saved-wallets

Lister mes porte-monnaie mobiles enregistrés

Les numéros mobile money enregistrés par le client, le porte-monnaie par défaut en premier. Le numéro n'est jamais renvoyé : opérateur et 4 derniers chiffres seulement. Un porte-monnaie pending n'a pas encore été vérifié : il ne peut pas financer un envoi.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/saved-wallets" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/saved-wallets",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "wallets": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "label": "texte",
      "provider": "airtel",
      "providerLabel": "texte",
      "last4": "texte",
      "maskedNumber": "texte",
      "status": "pending",
      "verified": true,
      "default": true,
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "max": 0
}

Réponses et erreurs

StatutSignification
200

Porte-monnaie enregistrés et nombre maximal.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/saved-wallets

Enregistrer un porte-monnaie mobile

Enregistre un numéro mobile money à votre nom. L'opérateur est lu depuis le numéro si provider est absent (saved_wallet_operator_unknown sinon). Le porte-monnaie est pending et un code de 6 chiffres est envoyé par SMS à ce numéro (5 minutes, 5 essais) : renvoyez-le à POST /v1/saved-wallets/{id}/verify avec le challengeId. Le numéro du compte, déjà vérifié, est enregistré verified d'emblée (challengeId nul). Erreurs : saved_wallet_limit (limite atteinte), saved_wallet_exists (déjà enregistré). Le même numéro enregistré par plusieurs clients ouvre une alerte de fraude.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
msisdnstringoui

Numéro mobile money de la RDC, avec ou sans +243.

providerstringnon

Opérateur ; lu depuis le numéro si absent.

airtel · mpesa · orange · afrimoney

labelstringnon

Nom du porte-monnaie ; l'opérateur par défaut.

Exemple de requête

{
  "msisdn": "+243810000000"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/saved-wallets" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "msisdn": "+243810000000"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "msisdn": "+243810000000"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/saved-wallets",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "msisdn": "+243810000000"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "msisdn": "+243810000000"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "wallet": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "label": "texte",
    "provider": "airtel",
    "providerLabel": "texte",
    "last4": "texte",
    "maskedNumber": "texte",
    "status": "pending",
    "verified": true,
    "default": true,
    "createdAt": "2026-10-01T09:30:00Z"
  },
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}

Réponses et erreurs

StatutSignification
201

Porte-monnaie enregistré.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

PATCH /v1/saved-wallets/{id}

Renommer un porte-monnaie ou le choisir par défaut

label : nom (1 à 40 caractères) ; default : true en fait le porte-monnaie proposé en premier (il doit être vérifié). Un champ absent est laissé tel quel.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Corps de la requête

NomTypeObligatoireDescription
labelstringnon
defaultbooleannon

Exemple de requête

{
  "label": "texte",
  "default": true
}

Exemple de code

curl -X PATCH "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "texte",
  "default": true
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "label": "texte",
  "default": true
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.patch(
    "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "label": "texte",
        "default": True
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "label": "texte",
    "default": true
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "label": "texte",
  "provider": "airtel",
  "providerLabel": "texte",
  "last4": "texte",
  "maskedNumber": "texte",
  "status": "pending",
  "verified": true,
  "default": true,
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Porte-monnaie mis à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

DELETE /v1/saved-wallets/{id}

Supprimer un porte-monnaie enregistré

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Exemple de code

curl -X DELETE "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.delete(
    "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Porte-monnaie supprimé.

Réponses et erreurs

StatutSignification
204

Porte-monnaie supprimé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/saved-wallets/{id}/code

Renvoyer le code de vérification d'un porte-monnaie

Nouveau code par SMS au numéro du porte-monnaie (limité comme les autres codes ; le précédent est invalidé). saved_wallet_verified si le porte-monnaie est déjà vérifié.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/code" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/code');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/code",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/code", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}

Réponses et erreurs

StatutSignification
200

Code envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/saved-wallets/{id}/verify

Vérifier un porte-monnaie avec le code reçu par SMS

Preuve que le client détient le numéro. Après un code juste, le porte-monnaie est verified et peut financer un envoi (source.savedWalletId). Un code faux, expiré ou épuisé renvoie l'erreur OTP habituelle.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

idcheminstringoui

Corps de la requête

NomTypeObligatoireDescription
challengeIdstring (uuid)oui
codestringoui

Code à 6 chiffres reçu par SMS au numéro du porte-monnaie.

Exemple de requête

{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "code": "••••••"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
        "code": "••••••"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/saved-wallets/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/verify", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "code": "••••••"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "label": "texte",
  "provider": "airtel",
  "providerLabel": "texte",
  "last4": "texte",
  "maskedNumber": "texte",
  "status": "pending",
  "verified": true,
  "default": true,
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Porte-monnaie vérifié.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/transfers/{reference}/saved-wallet

Enregistrer le numéro d'un envoi qui a abouti

Proposé à la fin d'un envoi par mobile money dont la collecte a abouti (GET /v1/transfers/{reference} : source mobile_money, numéro pas encore enregistré, limite non atteinte). Enregistre le numéro de l'envoi comme porte-monnaie pending et envoie le code de vérification à ce numéro (consentement journalisé : after_payment). saved_wallet_not_found si l'envoi ne s'y prête pas.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/saved-wallet" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/saved-wallet');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/saved-wallet",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/transfers/LP-7K2Q4F/saved-wallet", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "wallet": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "label": "texte",
    "provider": "airtel",
    "providerLabel": "texte",
    "last4": "texte",
    "maskedNumber": "texte",
    "status": "pending",
    "verified": true,
    "default": true,
    "createdAt": "2026-10-01T09:30:00Z"
  },
  "challengeId": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f"
}

Réponses et erreurs

StatutSignification
201

Porte-monnaie enregistré, code envoyé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me/dashboard

Afficher le tableau de bord

Soldes, actions rapides, envois en cours, favoris, taux, carte, plafond, sécurité, statistiques et dernières opérations.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
X-App-Iden-têtestringnon

Application mobile appelante.

X-App-Platformen-têtestringnon

Plateforme de l'application mobile.

X-App-Versionen-têtestringnon

Version de l'application (par exemple 1.4.2). Sous la version minimale, réponse 426 app_update_required.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me/dashboard" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/dashboard');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me/dashboard",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/dashboard", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "mode": "wallet",
  "kycLevel": 1,
  "balances": [
    {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    }
  ],
  "reserved": [
    {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    }
  ],
  "actions": {
    "send": true,
    "pay": true,
    "topup": true,
    "withdraw": true,
    "card": true
  },
  "transfersInProgress": [
    {
      "reference": "LP-7K2Q4F",
      "status": "in_progress",
      "steps": [
        {
          "label": "texte",
          "done": true
        }
      ],
      "beneficiary": "texte",
      "destination": "texte",
      "country": "KE",
      "source": "texte",
      "sourceType": "mobile_money",
      "send": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "fee": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "vat": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "levy": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "total": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "receive": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "rate": "texte",
      "createdAt": "2026-10-01T09:30:00Z",
      "deliveredAt": "2026-10-01T09:30:00Z",
      "refundedAt": "2026-10-01T09:30:00Z"
    }
  ],
  "favourites": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "fullName": "texte",
      "country": "KE",
      "payoutMethod": "mobile_money",
      "destination": "texte"
    }
  ],
  "rates": [
    {
      "country": "KE",
      "name": "texte",
      "payoutMethod": "mobile_money",
      "send": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "fee": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "receive": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      }
    }
  ],
  "card": {
    "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    "network": "visa",
    "last4": "texte",
    "status": "active",
    "balance": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    }
  },
  "monthlyLimit": {
    "used": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "cap": {
      "amount": 10000,
      "currency": "USD",
      "display": "texte"
    },
    "percent": 0,
    "level": 1
  },
  "security": {
    "twoFactor": true,
    "totp": true,
    "sms": true,
    "trustedDevices": 0,
    "lastLogin": "2026-10-01T09:30:00Z"
  },
  "statistics": {
    "months": [
      {
        "label": "texte",
        "sent": 0,
        "received": 0,
        "paid": 0
      }
    ],
    "max": 0,
    "destinations": [
      {
        "name": "texte",
        "count": 0,
        "percent": 0
      }
    ]
  },
  "recent": [
    {
      "type": "send",
      "label": "texte",
      "date": "2026-10-01T09:30:00Z",
      "statusLabel": "texte",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "reference": "LP-7K2Q4F",
      "receipt": true
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Tableau de bord du client.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/me/history

Afficher l'historique

Historique paginé, filtré par type et par texte (libellé ou référence).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
pagerequêteintegernon
perPagerequêteintegernon
typerequêtestringnon

Filtre. Valeur vide ou inconnue = tout.

qrequêtestringnon

Texte recherché dans le libellé ou la référence.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/me/history" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/me/history');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/me/history",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/me/history", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "items": [
    {
      "type": "send",
      "label": "texte",
      "date": "2026-10-01T09:30:00Z",
      "statusLabel": "texte",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "reference": "LP-7K2Q4F",
      "receipt": true
    }
  ],
  "page": 0,
  "perPage": 0,
  "total": 0,
  "hasMore": true,
  "filters": [
    "texte"
  ]
}

Réponses et erreurs

StatutSignification
200

Page d'historique.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/receipts/{reference}

Télécharger un reçu

Reçu PDF d'un envoi (LP-), d'un paiement marchand (TX-), d'un rechargement (TU-) ou d'une opération crypto (CX-).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Exemple de code

curl "https://sandbox.api.linc.cd/v1/receipts/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/receipts/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/receipts/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/receipts/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

Fichier (PDF ou image)

Réponses et erreurs

StatutSignification
200

Reçu PDF (pièce jointe recu-linc-{reference}.pdf).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/notifications

Lister mes notifications

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/notifications" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/notifications');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/notifications",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/notifications", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "notifications": [
    {
      "key": "texte",
      "title": "texte",
      "text": "texte",
      "date": "2026-10-01T09:30:00Z",
      "reference": "LP-7K2Q4F",
      "read": true
    }
  ],
  "unread": 0
}

Réponses et erreurs

StatutSignification
200

Notifications et nombre de non lues.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/notifications/{key}/read

Marquer une notification comme lue

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
keycheminstringoui

Clé de la notification, par exemple transfer:LP-7K2Q9M:delivered.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/notifications/texte/read" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/notifications/texte/read');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/notifications/texte/read",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/notifications/texte/read", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Notification lue.

Réponses et erreurs

StatutSignification
204

Notification lue.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/notifications/read-all

Tout marquer comme lu

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/notifications/read-all" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/notifications/read-all');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/notifications/read-all",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/notifications/read-all", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "marked": 0
}

Réponses et erreurs

StatutSignification
200

Nombre de notifications marquées.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/wallet/top-ups

Lister mes rechargements

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/wallet/top-ups" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/wallet/top-ups');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/wallet/top-ups",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/wallet/top-ups", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "topUps": [
    {
      "reference": "LP-7K2Q4F",
      "status": "pending",
      "provider": "airtel",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "failureReason": "texte",
      "createdAt": "2026-10-01T09:30:00Z",
      "completedAt": "2026-10-01T09:30:00Z"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Rechargements du client.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/wallet/top-ups

Recharger le solde

Collecte USSD / STK push sur le mobile money. Le résultat est asynchrone (suivez le statut).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Corps de la requête

NomTypeObligatoireDescription
providerstringnon

airtel · mpesa · orange · afrimoney

msisdnstringnon

Numéro à débiter. Vide = numéro du compte.

amountstringoui
currencystringnon

Exemple de requête

{
  "amount": "texte"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/wallet/top-ups" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": "texte"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/wallet/top-ups');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "amount": "texte"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/wallet/top-ups",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "amount": "texte"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/wallet/top-ups", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "amount": "texte"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 202

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "provider": "airtel",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "failureReason": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "completedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
202

Rechargement lancé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/wallet/top-ups/{reference}

Suivre un rechargement

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Exemple de code

curl "https://sandbox.api.linc.cd/v1/wallet/top-ups/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/wallet/top-ups/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/wallet/top-ups/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/wallet/top-ups/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "provider": "airtel",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "failureReason": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "completedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Rechargement.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/merchant-payments/resolve

Lire un QR marchand ou un lien de paiement

Ce que demande un QR scanné (EMVCo) ou un lien INV-… ouvert, avant de payer.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Corps de la requête

NomTypeObligatoireDescription
payloadstringoui

Contenu du QR EMVCo, lien https://app.linc.cd/pay/INV-… ou référence INV-….

Exemple de requête

{
  "payload": "texte"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/merchant-payments/resolve" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "payload": "texte"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/merchant-payments/resolve');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "payload": "texte"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/merchant-payments/resolve",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "payload": "texte"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/merchant-payments/resolve", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "payload": "texte"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "type": "link",
  "reference": "LP-7K2Q4F",
  "merchant": {
    "code": "••••••",
    "name": "texte",
    "country": "KE"
  },
  "label": "texte",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "status": "open",
  "payable": true,
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Marchand, montant et état du paiement demandé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/merchant-payments

Lister mes paiements marchands

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/merchant-payments" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/merchant-payments');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/merchant-payments",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/merchant-payments", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "payments": [
    {
      "reference": "LP-7K2Q4F",
      "status": "pending",
      "statusLabel": "texte",
      "merchant": {
        "code": "••••••",
        "name": "texte",
        "country": "KE"
      },
      "label": "texte",
      "channel": "link",
      "source": "mobile_money",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "createdAt": "2026-10-01T09:30:00Z",
      "paidAt": "2026-10-01T09:30:00Z",
      "refundedAt": "2026-10-01T09:30:00Z"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Paiements du client.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/merchant-payments

Payer un marchand

Paie un lien (INV-…) ou un QR de caisse (QR-…, montant obligatoire). Second facteur requis, sauf par carte bancaire : la réponse donne alors la page carte (cardCheckout) où la carte est saisie et confirmée par sa banque (3-D Secure). La collecte est asynchrone. Opération sensible : assertion X-Linc-Attestation exigée des applications attestées.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
referencestringoui
amountstringnon

Obligatoire pour un QR de caisse (USD).

sourceobjectnon
source.typestringnon

mobile_money · wallet · card

source.providerstringnon

airtel · mpesa · orange · afrimoney

source.msisdnstringnon
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "reference": "INV-7K2Q4F",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/merchant-payments" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reference": "INV-7K2Q4F",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/merchant-payments');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "reference": "INV-7K2Q4F",
  "source": {
    "type": "mobile_money",
    "provider": "airtel",
    "msisdn": "+243970000000"
  },
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/merchant-payments",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "reference": "INV-7K2Q4F",
        "source": {
            "type": "mobile_money",
            "provider": "airtel",
            "msisdn": "+243970000000"
        },
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/merchant-payments", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "reference": "INV-7K2Q4F",
    "source": {
      "type": "mobile_money",
      "provider": "airtel",
      "msisdn": "+243970000000"
    },
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 202

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "statusLabel": "texte",
  "merchant": {
    "code": "••••••",
    "name": "texte",
    "country": "KE"
  },
  "label": "texte",
  "channel": "link",
  "source": "mobile_money",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "createdAt": "2026-10-01T09:30:00Z",
  "paidAt": "2026-10-01T09:30:00Z",
  "refundedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
202

Paiement accepté, en cours.

422

Refus métier (Problem.code), dont journey_limit_exceeded : le montant dépasse un plafond du parcours de paiement (par envoi, par jour ou par mois, en USD quelle que soit la devise envoyée, docs/adr/0083). detail donne le plafond atteint (« 30.00 USD »). Un parcours fermé répond operation_unavailable (403), sans motif.

Erreur au format application/problem+json : voir « Erreurs ».

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/merchant-payments/{reference}

Afficher un paiement marchand

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence du paiement marchand.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/merchant-payments/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/merchant-payments/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/merchant-payments/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/merchant-payments/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "status": "pending",
  "statusLabel": "texte",
  "merchant": {
    "code": "••••••",
    "name": "texte",
    "country": "KE"
  },
  "label": "texte",
  "channel": "link",
  "source": "mobile_money",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "createdAt": "2026-10-01T09:30:00Z",
  "paidAt": "2026-10-01T09:30:00Z",
  "refundedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Paiement marchand.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/withdrawal-codes

Lister mes codes de retrait

Le code complet n'est jamais renvoyé (code = null).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/withdrawal-codes" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/withdrawal-codes');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/withdrawal-codes",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/withdrawal-codes", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "codes": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "status": "active",
      "statusLabel": "texte",
      "code": "••••••",
      "last4": "texte",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "createdAt": "2026-10-01T09:30:00Z",
      "expiresAt": "2026-10-01T09:30:00Z",
      "closedAt": "2026-10-01T09:30:00Z"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Codes de retrait.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/withdrawal-codes

Créer un code de retrait

Code à 8 chiffres, affiché une seule fois, à donner à l'agent avec une pièce d'identité. Le montant est réservé. Second facteur requis. Opération sensible (X-Linc-Attestation).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
amountstringoui
currencystringnon
twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "amount": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/withdrawal-codes" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/withdrawal-codes');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "amount": "texte",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/withdrawal-codes",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "amount": "texte",
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/withdrawal-codes", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "amount": "texte",
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "status": "active",
  "statusLabel": "texte",
  "code": "••••••",
  "last4": "texte",
  "amount": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "createdAt": "2026-10-01T09:30:00Z",
  "expiresAt": "2026-10-01T09:30:00Z",
  "closedAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
201

Code créé (champ code présent une seule fois).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/withdrawal-codes/{id}/cancel

Annuler un code de retrait

Libère le montant réservé.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/withdrawal-codes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/cancel" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/withdrawal-codes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/cancel');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/withdrawal-codes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/cancel",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/withdrawal-codes/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/cancel", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 204

Code annulé.

Réponses et erreurs

StatutSignification
204

Code annulé.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/cards

Lister mes cartes virtuelles

Cartes du client et programmes ouverts à la création.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/cards" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/cards",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "cards": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "last4": "texte",
      "network": "visa",
      "currency": "USD",
      "embossedName": "texte",
      "status": "active",
      "frozenByCompliance": true,
      "model": "companion",
      "balance": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      },
      "limits": {
        "perTransaction": 0,
        "daily": 0,
        "monthly": 0,
        "ecommerce": true
      },
      "closeReason": "texte",
      "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "programmes": [
    {
      "network": "visa",
      "currency": "USD"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Cartes et programmes ouverts.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards

Créer une carte virtuelle

Mode wallet et KYC niveau 2 requis. Second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
networkstringnon

visa · mastercard

embossedNamestringnon
twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "network": "visa",
  "embossedName": "AMANI K",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "network": "visa",
  "embossedName": "AMANI K",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "network": "visa",
  "embossedName": "AMANI K",
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "network": "visa",
        "embossedName": "AMANI K",
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "network": "visa",
    "embossedName": "AMANI K",
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0192a7c4-7a13-7d0b-b8c4-1e5f6a2b3c44",
  "last4": "4821",
  "network": "visa",
  "currency": "USD",
  "embossedName": "AMANI K",
  "status": "active",
  "frozenByCompliance": false,
  "model": "companion",
  "balance": {
    "amount": 0,
    "currency": "USD",
    "display": "0,00 $"
  },
  "limits": {
    "perTransaction": 100000,
    "daily": 200000,
    "monthly": 500000,
    "ecommerce": true
  },
  "closeReason": null,
  "replacedBy": null,
  "createdAt": "2026-09-29T14:02:00+00:00"
}

Réponses et erreurs

StatutSignification
201

Carte créée.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/cards/{id}

Afficher une carte

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "last4": "texte",
  "network": "visa",
  "currency": "USD",
  "embossedName": "texte",
  "status": "active",
  "frozenByCompliance": true,
  "model": "companion",
  "balance": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "limits": {
    "perTransaction": 0,
    "daily": 0,
    "monthly": 0,
    "ecommerce": true
  },
  "closeReason": "texte",
  "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/cards/{id}/transactions

Lister les opérations d'une carte

Paiements, refus et chargements, du plus récent au plus ancien (100 au plus).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/transactions" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/transactions');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/transactions",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/transactions", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "transactions": [
    {
      "kind": "payment",
      "label": "texte",
      "date": "2026-10-01T09:30:00Z",
      "status": "texte",
      "detail": "texte",
      "amount": {
        "amount": 10000,
        "currency": "USD",
        "display": "texte"
      }
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Opérations de la carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/freeze

Geler une carte

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/freeze" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/freeze');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/freeze",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/freeze", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "last4": "texte",
  "network": "visa",
  "currency": "USD",
  "embossedName": "texte",
  "status": "active",
  "frozenByCompliance": true,
  "model": "companion",
  "balance": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "limits": {
    "perTransaction": 0,
    "daily": 0,
    "monthly": 0,
    "ecommerce": true
  },
  "closeReason": "texte",
  "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/unfreeze

Dégeler une carte

Impossible si la conformité a gelé la carte.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/unfreeze" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/unfreeze');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/unfreeze",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/unfreeze", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "last4": "texte",
  "network": "visa",
  "currency": "USD",
  "embossedName": "texte",
  "status": "active",
  "frozenByCompliance": true,
  "model": "companion",
  "balance": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "limits": {
    "perTransaction": 0,
    "daily": 0,
    "monthly": 0,
    "ecommerce": true
  },
  "closeReason": "texte",
  "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/reveal

Afficher les détails de la carte

Retourne une session d'affichage (60 s) pour le SDK de l'émetteur, après un second facteur. Aucune donnée de carte ne transite par Linc.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/reveal" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/reveal');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/reveal",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/reveal", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "issuer": "texte",
  "cardReference": "LP-7K2Q4F",
  "last4": "texte",
  "sdkUrl": "https://example.com",
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Session d'affichage.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/replace

Remplacer une carte

Ferme la carte (perdue ou compromise) et en crée une nouvelle. Second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
reasonstringnon

lost · compromised

twoFactorobjectoui

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringoui

totp · sms · backup_code

twoFactor.codestringoui
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/replace" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/replace');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/replace",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/replace", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "last4": "texte",
  "network": "visa",
  "currency": "USD",
  "embossedName": "texte",
  "status": "active",
  "frozenByCompliance": true,
  "model": "companion",
  "balance": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "limits": {
    "perTransaction": 0,
    "daily": 0,
    "monthly": 0,
    "ecommerce": true
  },
  "closeReason": "texte",
  "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
201

Nouvelle carte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/terminate

Fermer une carte

Fermeture définitive. Second facteur requis.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/terminate" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/terminate');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/terminate",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/terminate", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "last4": "texte",
  "network": "visa",
  "currency": "USD",
  "embossedName": "texte",
  "status": "active",
  "frozenByCompliance": true,
  "model": "companion",
  "balance": {
    "amount": 10000,
    "currency": "USD",
    "display": "texte"
  },
  "limits": {
    "perTransaction": 0,
    "daily": 0,
    "monthly": 0,
    "ecommerce": true
  },
  "closeReason": "texte",
  "replacedBy": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
  "createdAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
200

Carte fermée.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/cards/{id}/credential-show-session

Ouvrir une session d'affichage de la carte (SDK mobile)

Même contrôle que reveal (second facteur, audit) pour le SDK Credential Show de l'émetteur sur Android et iOS. L'application passe cardReference au SDK, qui affiche les détails lui-même. Opération sensible (X-Linc-Attestation).

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
idcheminstringoui

Identifiant de la carte.

X-App-Platformen-têtestringnon

Plateforme de l'application mobile.

X-Linc-Attestationen-têtestringnon

Assertion de l'installation attestée, pour une opération sensible. Hachage de la requête : base64url(SHA-256(METHOD "\n" PATH "\n" Idempotency-Key "\n" hex(SHA-256(corps)))). Android : jeton Play Integrity (requête standard) avec ce requestHash. iOS : assertion App Attest (CBOR en base64) sur le SHA-256 de ce hachage. Absente ou invalide quand la politique l'exige : 403 attestation_required.

Corps de la requête

NomTypeObligatoireDescription
twoFactorobjectnon

Preuve de second facteur. Pour sms, joignez le challengeId du code reçu. Certaines opérations demandent un code saisi à l'instant, jamais un code de secours : le code de l'application d'authentification quand elle est activée depuis un certain temps, sinon un code SMS envoyé au téléphone vérifié (à demander avec POST /v1/me/security/otp, même si la double authentification par SMS n'est pas activée). Un autre moyen répond two_factor_method_unavailable (422), avec le moyen attendu dans le message. Quand aucun moyen ne convient, l'opération répond operation_unavailable (403) ou est mise en attente.

twoFactor.methodstringnon

totp · sms · backup_code

twoFactor.codestringnon
twoFactor.challengeIdstring (uuid)non

Exemple de requête

{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/credential-show-session" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/credential-show-session');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "twoFactor": {
    "method": "totp",
    "code": "••••••"
  }
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/credential-show-session",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "twoFactor": {
            "method": "totp",
            "code": "••••••"
        }
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/cards/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f/credential-show-session", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "twoFactor": {
      "method": "totp",
      "code": "••••••"
    }
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "issuer": "texte",
  "cardReference": "LP-7K2Q4F",
  "last4": "texte",
  "platform": "android",
  "expiresAt": "2026-10-01T09:30:00Z"
}

Réponses et erreurs

StatutSignification
201

Session pour le SDK Credential Show de l'émetteur.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/tickets/options

Lister les types et catégories de demande

Types (réclamation, demande d'information), catégories et contraintes des pièces jointes.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/tickets/options" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/options');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/tickets/options",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/options", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "types": [
    {
      "code": "complaint",
      "label": "texte"
    }
  ],
  "categories": [
    {
      "code": "transfer",
      "label": "texte"
    }
  ],
  "attachments": {
    "types": [
      "texte"
    ],
    "maxBytes": 0
  }
}

Réponses et erreurs

StatutSignification
200

Options du formulaire de demande.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/tickets

Lister mes demandes

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Exemple de code

curl "https://sandbox.api.linc.cd/v1/tickets" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/tickets",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "items": [
    {
      "reference": "LP-7K2Q4F",
      "type": "complaint",
      "category": "transfer",
      "categoryLabel": "texte",
      "subject": "texte",
      "linkedReference": "LP-7K2Q4F",
      "status": "received",
      "statusLabel": "texte",
      "createdAt": "2026-10-01T09:30:00Z",
      "updatedAt": "2026-10-01T09:30:00Z"
    }
  ]
}

Réponses et erreurs

StatutSignification
200

Demandes du client, de la plus récente à la plus ancienne.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/tickets

Ouvrir une demande

Ouvre une réclamation ou une demande d'information (référence TK-XXXXXX). Erreur 422 validation_failed ou ticket_invalid si le formulaire est incomplet.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Corps de la requête

NomTypeObligatoireDescription
typestringoui

complaint : réclamation ; information : demande d'information.

complaint · information

categorystringoui

transfer · merchant_payment · top_up · withdrawal_agent · card · kyc · account_security · fraud · technical · other

subjectstringoui
descriptionstringoui
linkedReferencestringnon

LP-…, INV-…, TX-…, TU-…, AG-…, QR-…, CL-…, RG-… ou CARD-1234 (4 derniers chiffres).

Exemple de requête

{
  "type": "complaint",
  "category": "transfer",
  "subject": "texte",
  "description": "texte"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/tickets" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "complaint",
  "category": "transfer",
  "subject": "texte",
  "description": "texte"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "type": "complaint",
  "category": "transfer",
  "subject": "texte",
  "description": "texte"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/tickets",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "type": "complaint",
        "category": "transfer",
        "subject": "texte",
        "description": "texte"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "type": "complaint",
    "category": "transfer",
    "subject": "texte",
    "description": "texte"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
201

Demande ouverte.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/tickets/{reference}

Afficher une demande

Fil des échanges, pièces jointes et actions possibles. Erreur 404 ticket_not_found.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
200

Demande.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/tickets/{reference}/messages

Répondre à une demande

Ajoute un message au fil. Erreur 404 ticket_not_found, 409 ticket_closed si la demande est clôturée.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Corps de la requête

NomTypeObligatoireDescription
bodystringoui

Exemple de requête

{
  "body": "texte"
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/messages" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "texte"
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/messages');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16)), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "body": "texte"
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/messages",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "body": "texte"
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/messages", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" },
  body: JSON.stringify({
    "body": "texte"
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
201

Demande mise à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/tickets/{reference}/attachments

Joindre un fichier à une demande

Envoie un fichier dans le champ multipart file (PDF, JPEG ou PNG, 10 Mo maximum), analysé par l'antivirus avant de pouvoir être lu. Erreurs 422 attachment_type_refused ou attachment_too_large, 409 attachment_limit_reached.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

Corps de la requête

Fichier envoyé en multipart/form-data.

NomTypeObligatoireDescription
filestringoui

Fichier (PDF, JPEG ou PNG, 10 Mo maximum).

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -F "file=@document.jpg"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_POSTFIELDS => ['file' => new CURLFile('document.jpg')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    files={"file": open("document.jpg", "rb")},
    timeout=30,
)
print(answer.status_code, answer.text)
import { openAsBlob } from "node:fs";

const form = new FormData();
form.append("file", await openAsBlob("document.jpg"), "document.jpg");

const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
  body: form,
});
console.log(answer.status, await answer.text());

Exemple de réponse 201

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
201

Demande mise à jour.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

GET /v1/tickets/{reference}/attachments/{id}

Télécharger une pièce jointe

Adresse renvoyée par …/attachments/{id}/link, valable 5 minutes et liée à l'utilisateur qui l'a demandée ; le jeton d'accès reste exigé. Erreurs 403 attachment_link_invalid (lien expiré, altéré ou d'un autre utilisateur), 409 attachment_unavailable.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

idcheminstringoui

Identifiant de la pièce jointe.

viewerrequêtestringoui

Utilisateur auquel le lien est lié (fourni par le lien signé).

_expiresrequêtestringoui

Expiration du lien (fournie par le lien signé).

_signaturerequêtestringoui

Signature du lien.

Exemple de code

curl "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f?viewer=texte&_expires=texte&_signature=texte" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f?viewer=texte&_expires=texte&_signature=texte');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.get(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f?viewer=texte&_expires=texte&_signature=texte",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/attachments/0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f?viewer=texte&_expires=texte&_signature=texte", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}` },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

Fichier (PDF ou image)

Réponses et erreurs

StatutSignification
200

Contenu de la pièce jointe (téléchargement, jamais mis en cache).

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/tickets/{reference}/reopen

Rouvrir une demande

Possible pendant un délai après la résolution (reopenUntil). Erreur 409 ticket_not_reopenable.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Opération financière : envoyez un Idempotency-Key unique par opération (rejoué 24 h).

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

Idempotency-Keyen-têtestringoui

Identifiant unique de l'opération (par exemple un UUID), conservé 24 h. Une même clé avec le même corps rejoue la réponse d'origine. Avec un autre corps : 422 idempotency_key_reused. Pendant le traitement : 409 idempotency_in_progress.

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/reopen" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/reopen');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Idempotency-Key: ' . bin2hex(random_bytes(16))],
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os
import uuid

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/reopen",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/reopen", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Idempotency-Key": crypto.randomUUID() },
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
200

Demande.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».

POST /v1/tickets/{reference}/satisfaction

Noter le traitement d'une demande

Une seule note par demande résolue ou clôturée. Erreurs 409 ticket_already_rated, 422 validation_failed.

Authentification : Jeton client : Authorization: Bearer <jeton d'accès>

Paramètres

NomOùTypeObligatoireDescription
referencecheminstringoui

Référence publique de la demande.

Corps de la requête

NomTypeObligatoireDescription
scoreintegeroui
commentstringnon

Exemple de requête

{
  "score": 0
}

Exemple de code

curl -X POST "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/satisfaction" \
  -H "Authorization: Bearer $LINC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "score": 0
}'
<?php
$ch = curl_init('https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/satisfaction');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('LINC_ACCESS_TOKEN'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => <<<'JSON'
{
  "score": 0
}
JSON,
    CURLOPT_RETURNTRANSFER => true,
]);
$answer = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL;
print_r($answer);
import os

import requests

answer = requests.post(
    "https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/satisfaction",
    headers={"Authorization": f"Bearer {os.environ['LINC_ACCESS_TOKEN']}"},
    json={
        "score": 0
    },
    timeout=30,
)
print(answer.status_code, answer.text)
const answer = await fetch("https://sandbox.api.linc.cd/v1/tickets/LP-7K2Q4F/satisfaction", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.LINC_ACCESS_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "score": 0
  }),
});
console.log(answer.status, await answer.text());

Exemple de réponse 200

{
  "reference": "LP-7K2Q4F",
  "type": "complaint",
  "category": "transfer",
  "categoryLabel": "texte",
  "subject": "texte",
  "linkedReference": "LP-7K2Q4F",
  "status": "received",
  "statusLabel": "texte",
  "createdAt": "2026-10-01T09:30:00Z",
  "updatedAt": "2026-10-01T09:30:00Z",
  "messages": [
    {
      "author": "texte",
      "mine": true,
      "body": "texte",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "attachments": [
    {
      "id": "0190f1b4-7c3a-7d2e-9a51-3f2b8c1d4e5f",
      "filename": "texte",
      "mimeType": "application/pdf",
      "size": 0,
      "mine": true,
      "scan": "pending",
      "createdAt": "2026-10-01T09:30:00Z"
    }
  ],
  "canReply": true,
  "canReopen": true,
  "reopenUntil": "2026-10-01T09:30:00Z",
  "canRate": true,
  "satisfaction": 0,
  "suggestedActions": [
    "freeze_card"
  ]
}

Réponses et erreurs

StatutSignification
200

Demande.

Toute autre erreur

Erreur (RFC 9457).

Erreur au format application/problem+json : voir « Erreurs ».