Référence
SDKs officiels
Surface API miroir sur les 3 langages : PHP (stable), Node.js (alpha), Python (alpha). Tous incluent OAuth2 auto-refresh, idempotency intégrée, retry exponentiel sur 5xx, et un hook onRetry pour l'observabilité.
Distribution : via le dépôt pour l'instant (publication Packagist / npm / PyPI planifiée). L'API REST reste intégrable sans SDK — cf. Démarrage rapide.
Surface commune
| Méthode | Endpoint |
|---|---|
| obtainAccessToken | POST /oauth/token |
| openSmsSession / openTotpSession | POST /v1/sessions |
| validateOtp | POST /v1/sessions/{id}/validate |
| recordAction | POST /v1/sessions/{id}/actions |
| attachArtifact | POST /v1/sessions/{id}/artifacts |
| closeSession | POST /v1/sessions/{id}/close |
| getProof / downloadProofBundle | POST /v1/proofs |
| getTimeline | GET /v1/timelines |
| setOnRetry | (hook observabilité) |
PHP — composer require session-proof/php-sdk
use SessionProof\Client;
$client = new Client(
baseUrl: 'https://proof.example',
organisationId: '01900000-...',
);
$client->obtainAccessToken('sp_secret'); // auto-refresh à 60s avant expiry
$session = $client->openSession('sms', 'user-1', [
'phone_number' => '+33600000001',
'beneficiary_email' => 'alice@example.com',
'planned_operations' => [
['op_id' => 'ctr-001', 'type' => 'INTENT_DECLARED', 'payload_hash' => '...'],
],
]);
$client->validate($session['session_id'], '000000');
$client->recordAction($session['session_id'], 'INTENT_DECLARED', '...', ['op_id' => 'ctr-001']);
$client->close($session['session_id']);
$bundle = $client->getProof($session['session_id']); // ou attendre bundle.generated (anchor_coverage: complete)
file_put_contents('bundle.asice', $bundle);
Node.js — bun add @session-proof/sdk
import { Client } from '@session-proof/sdk';
const client = new Client({
baseUrl: 'https://proof.example',
organisationId: '01900000-...',
});
await client.obtainAccessToken('sp_secret');
const session = await client.openSmsSession({
actorUserId: 'user-1',
phoneNumber: '+33600000001',
idempotencyKey: 'open-42',
});
await client.validateOtp(session.session_id, '000000');
await client.recordAction(session.session_id, 'VALIDATION_ACTION', '...', { op_id: 'ctr-001' });
await client.closeSession(session.session_id);
const bundle = await client.downloadProofBundle(session.session_id);
await Bun.write('bundle.asice', bundle);
// Observabilité retry
client.setOnRetry((attempt, status, delayMs) => {
console.warn(`retry attempt=${attempt} status=${status} delay=${delayMs}ms`);
});
Python — pip install session-proof-sdk
from session_proof import Client
client = Client(
base_url="https://proof.example",
organisation_id="01900000-...",
)
client.obtain_access_token("sp_secret")
session = client.open_sms_session(
actor_user_id="user-1",
phone_number="+33600000001",
beneficiary_email="alice@example.com",
idempotency_key="open-42",
)
client.validate_otp(session["session_id"], "000000")
client.record_action(session["session_id"], "VALIDATION_ACTION", "...", metadata={"op_id": "ctr-001"})
client.close_session(session["session_id"])
bundle: bytes = client.download_proof_bundle(session["session_id"])
open("bundle.asice", "wb").write(bundle)
# Observabilité retry
client.set_on_retry(lambda attempt, status, delay_ms:
print(f"retry attempt={attempt} status={status} delay={delay_ms}ms"))
Exceptions typées
Les 3 SDK exposent 12-13 exceptions typées qui mappent les codes d'erreur métier (OTP_EXPIRED, SESSION_CLOSED, ORGANISATION_SUSPENDED, etc.). Catch précis plutôt que des string-comparisons.
try {
await client.validateOtp(sessionId, otp);
} catch (e) {
if (e instanceof OtpInvalidException) console.log(`attempts left: ${e.attemptsLeft}`);
if (e instanceof OtpExpiredException) refreshOtp();
if (e instanceof SessionNotFoundException) ...;
}
- Timeline paginator (générateur asynchrone qui suit
next_cursor) - SDK Swift + Kotlin pour mobile
- Webhook subscriptions client-side helper (vérification HMAC)