Skip to content

SDK TypeScript

Le SDK @opcovia/sdk fournit un client type pour interagir avec l'API Opcovia depuis Node.js ou tout runtime compatible avec fetch.

Installation

bash
pnpm add @opcovia/sdk

Creer un client

typescript
import { OpcoviaClient } from '@opcovia/sdk'

const client = new OpcoviaClient({
  baseUrl: 'http://localhost:3000',
  apiKey: 'votre-cle-api',
  timeout: 30_000, // optionnel, 30s par defaut
})

Lire un dossier

Par numero interne :

typescript
const dossier = await client.getDossier('opco-ep', {
  numeroInterne: '12345',
})

Par numero externe + numero DECA :

typescript
const dossier = await client.getDossier('opco-ep', {
  numeroExterne: 'EXT-001',
  numeroDeca: 'DECA-001',
})

Lister les etats de dossiers

typescript
const etats = await client.getDossierEtats('opco-ep', {
  anneeDossier: 2026,
  dateModification: '2026-01-01',
})

Les deux parametres sont optionnels et servent a filtrer les resultats.

Transmettre un dossier (POST asynchrone)

Les POST retournent un jobId et une statusUrl. Le traitement est asynchrone.

typescript
const { jobId, statusUrl } = await client.postDossier(
  'opco-ep',
  {
    employeur: { siret: '12345678901234', raisonSociale: 'Mon entreprise' },
    apprenti: { nom: 'Dupont', prenom: 'Jean' },
    // ... autres champs cerfa
  },
  'idempotency-key-unique', // optionnel, garantit l'idempotence
)

console.log(`Job cree : ${jobId}`)
console.log(`Suivi : ${statusUrl}`)

Diagramme du flux asynchrone

Suivre un job

Polling manuel

typescript
const status = await client.getJobStatus('opco-ep', jobId)

if (status.status === 'completed') {
  console.log('Resultat :', status.result)
} else if (status.status === 'failed') {
  console.error('Erreur :', status.error)
}

Attente automatique

waitForJob interroge le statut en boucle jusqu'a completion ou echec :

typescript
try {
  const result = await client.waitForJob('opco-ep', jobId, 60_000) // timeout 60s
  console.log('Job termine :', result.status)
  console.log('Resultat :', result.result)
} catch (error) {
  // Timeout depasse sans completion
  console.error(error.message)
}

Bulk sync

Lancez une synchronisation complete de tous les dossiers d'un CFA :

typescript
// Demarrer le sync
const { syncId, statusUrl } = await client.startSync('opco-ep', {
  order: 'recent_first', // ou 'oldest_first'
})

// Suivre la progression
const status = await client.getSyncStatus(syncId)
console.log(`Progression : ${status.progress * 100}%`)
console.log(`Recuperes : ${status.fetched} / ${status.total}`)

Le sync fonctionne en deux phases :

  1. Discovery -- recuperation de tous les IDs via GET /dossiers/etats
  2. Fetch -- recuperation par batches de 50 via GET /dossiers/liste

Des webhooks sync.started, sync.batch et sync.completed sont emis a chaque etape.

Webhooks

Enregistrer un webhook

typescript
const webhook = await client.createWebhook(
  'https://mon-app.example.com/webhooks/opcovia',
  ['dossier.etat_changed', 'sync.completed'],
)

// Conservez le secret pour verifier les signatures
console.log('Webhook ID :', webhook.id)
console.log('Secret HMAC :', webhook.secret)

Lister et supprimer

typescript
const webhooks = await client.listWebhooks()

await client.deleteWebhook(webhook.id)

Verifier la signature

Quand Opcovia envoie une notification, le payload est signe via HMAC-SHA256. Le header Opcovia-Signature contient la signature a verifier.

typescript
import { OpcoviaClient } from '@opcovia/sdk'

function handleWebhook(req: Request) {
  const payload = req.body // string brut du body
  const signature = req.headers['opcovia-signature']
  const secret = 'votre-webhook-secret'

  const valid = OpcoviaClient.verifySignature(payload, signature, secret)

  if (!valid) {
    throw new Error('Signature invalide')
  }

  const event = JSON.parse(payload)
  console.log('Evenement recu :', event)
}

Flux de reception d'un webhook

Gestion des erreurs

Le SDK leve une OpcoviaApiError pour toute reponse non-2xx :

typescript
import { OpcoviaApiError } from '@opcovia/sdk'

try {
  await client.getDossier('opco-ep', { numeroInterne: 'inexistant' })
} catch (error) {
  if (error instanceof OpcoviaApiError) {
    console.error(`Erreur ${error.status}`)
    console.error('Code :', error.body.code)
    console.error('Description :', error.body.description)
  }
}

Codes d'erreur courants :

StatusCodeDescription
400VALIDATION_ERRORRequete invalide (champs manquants, format incorrect)
403FORBIDDENCle API invalide ou absente
404NOT_FOUNDRessource introuvable
429RATE_LIMITEDTrop de requetes, reessayez plus tard
501NOT_SUPPORTEDOperation non supportee par cet OPCO
502UPSTREAM_ERRORErreur de l'API OPCO en amont

Types exportes

Le SDK exporte les types suivants :

typescript
import type { OpcoviaConfig, JobStatus, SyncStatus } from '@opcovia/sdk'
  • OpcoviaConfig -- configuration du client (baseUrl, apiKey, timeout)
  • JobStatus -- statut d'un job async (jobId, status, result, error)
  • SyncStatus -- statut d'un bulk sync (syncId, status, total, fetched, progress)