DPAE — Déclaration Préalable À l'Embauche
L'API partenaire Pesia permet de déposer des DPAE en lot, de suivre les retours URSSAF et de demander une annulation avant le début de l'envoi. Pesia constitue le dossier employeur à partir de votre agence. Vous fournissez les données du salarié et du contrat.
Un HTTP 202 confirme la prise en charge par Pesia. Il ne vaut pas acceptation par l'URSSAF.
Enregistrement du salarié dans Pesia
En sandbox, aucun salarié ni profil agence n'est créé ou modifié.
Pour une nouvelle DPAE en production, worker.external_id déclenche une tentative d'enregistrement du salarié et de son profil agence. Ce champ reste obligatoire dans l'API partenaire.
Pesia tente cet enregistrement après la validation de la requête et le contrôle du mandat, avant le dépôt asynchrone.
Une annulation ou un rejet URSSAF ultérieur n'annule pas les modifications du salarié ou de son profil.
employeeRegistration décrit le résultat de cette tentative. Il ne décrit pas l'état actuel de la fiche salarié.
Un CTT utilise un profil INTERIM. Un CDD ou CDI utilise un profil PERMANENT. Les deux types peuvent coexister pour la même personne dans la même agence. Pesia réutilise le type demandé ou le crée, sans convertir l'autre profil ni modifier son statut ou ses dates.
Le dépôt URSSAF utilise toujours l'identité que vous fournissez, après complétion et validation. Pesia compare le NIR et le matricule dans votre organisation. En cas de contradiction avec une fiche existante, Pesia ne fusionne pas les fiches et ne remplace pas les données d'état civil connues. Les données civiles absentes peuvent être complétées. Le nom d'usage et l'adresse fournis peuvent être mis à jour lorsque l'identité concorde.
Le champ employeeRegistration décrit cette opération séparément du dépôt :
status | Signification |
|---|---|
created | Salarié et profil agence créés. |
updated | Fiche complétée ou modifiée, ou profil agence ajouté. |
unchanged | Salarié et profil déjà enregistrés, sans modification. |
skipped | Aucun enregistrement ; reason: sandbox en sandbox. |
failed | Enregistrement annulé ; la DPAE valide reste prise en charge. |
Les trois statuts de succès portent employeeId, profileId et profileType.
Un échec porte code et message. Les codes sont DPAE_EMPLOYEE_IDENTITY_CONFLICT et DPAE_EMPLOYEE_REGISTRATION_FAILED.
Ce résultat est disponible au dépôt et à la consultation. Il peut être absent pour une ancienne soumission.
{
"contractExternalId": "MISSION-42",
"workerExternalId": "SAL-7",
"submissionId": "00000000-0000-4000-8000-000000000001",
"status": "SCHEDULED",
"ok": true,
"duplicate": false,
"employeeRegistration": {
"status": "failed",
"code": "DPAE_EMPLOYEE_REGISTRATION_FAILED",
"message": "Le salarié et son profil agence n’ont pas pu être enregistrés. La DPAE utilise les données fournies."
}
}
Dans cet exemple, ne redéposez pas la DPAE pour réparer la fiche salarié. Suivez sa soumission et contactez Pesia pour la fiche. Une erreur de validation de l'identité ou du contrat reste bloquante pour l'élément concerné. L'absence de mandat actif bloque le dépôt. Un nouveau dépôt d'une référence déjà active retourne son résultat enregistré, sans nouvelle écriture salarié.
Prérequis
- Scope requis :
dpae:write(voir Scopes) — il couvre le dépôt et la lecture des soumissions DPAE. - Le
agencyCodede chaque élément doit correspondre à une agence de votre organisation. Avec le scopeagency:read, utilisez le champcoderetourné parGET /partner/v1/agencies. Respectez sa casse exacte. - L'agence doit disposer d'un profil déclarant complet et d'un mandat de déclaration URSSAF actif chez Pesia. Si ce n'est pas le cas, contactez votre interlocuteur Pesia (partenaires@pesia.fr).
Le bloc employeur (SIRET, code URSSAF, adresse de l'établissement) est dérivé automatiquement de l'agence par Pesia — vous ne l'envoyez pas.
Déposer des DPAE
POST /partner/v1/dpae/submissions accepte un lot de 1 à 200 éléments. Le header
Idempotency-Key est obligatoire (UUIDv4 ou ULID).
Les retours URSSAF sont suivis par soumission. Une anomalie ne signifie pas que toutes les embauches de l'agence sont rejetées. Un retour qui ne permet pas d'identifier les embauches concernées ne produit pas de rejet collectif supposé : les soumissions en attente conservent leur statut. Contactez Pesia si un statut reste bloqué.
Utilisez les identifiants de l'environnement souhaité et le même header X-Pesia-Env
pour déposer, consulter et annuler. Une soumission sandbox est invisible en production,
et inversement : une lecture ou une annulation par son identifiant renvoie 404.
L'historique et la déduplication sont aussi séparés par organisation et environnement.
Exemple fictif : adaptez les identifiants, les dates et les données à votre embauche.
curl -X POST https://api.pesia.fr/partner/v1/dpae/submissions \
-H "Authorization: Bearer <token>" \
-H "Idempotency-Key: 3f6f0c9a-0b1e-4c9d-9a4a-3d2f8e6c1b7d" \
-H "X-Pesia-Env: production" \
-H "Content-Type: application/json" \
-d '{
"submissions": [
{
"agencyCode": "AG-PARIS-01",
"worker": {
"external_id": "MAT-4207",
"last_name": "MARTIN",
"first_names": ["Camille"],
"sex": "02",
"birth": { "date": "1994-03-12", "city": "Lyon", "department": "69", "country": "FR" },
"nir": "2940369123222",
"nir_key": "43",
"address": { "street": "12 rue de la République", "postal_code": "69002", "city": "Lyon" }
},
"contract": {
"external_id": "CTT-2026-078451",
"nature": "CTT",
"start_date": "2026-07-15",
"start_time": "08:00:00",
"end_date": "2026-07-31",
"trial_time": "2"
}
}
]
}'
Champs de la requête
Le bloc worker reprend le vocabulaire des lots de paie.
Les DPAE portent les prénoms dans first_names (tableau), avec une date de naissance complète.
Certains champs d'identité peuvent être déduits du NIR, selon les règles ci-dessous.
workerExternalId est retourné dans les résultats du POST. Le suivi GET et les
webhooks portent contractExternalId, mais pas workerExternalId. Conservez votre
correspondance entre contrat, salarié et submissionId.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
agencyCode | string | Oui | Valeur exacte du champ code retourné par GET /partner/v1/agencies avec le scope agency:read. Respectez la casse. |
worker.external_id | string | Oui | Matricule du salarié dans votre système — même champ et même règle que dans les lignes des lots de paie : Pesia retire les blancs au début et à la fin, puis normalise le matricule en Unicode NFC. |
worker.last_name | string | Oui | Nom de naissance du salarié (32 caractères maximum). |
worker.usual_name | string | Non | Nom d'usage, s'il diffère du nom de naissance. |
worker.first_names | string[] | Oui | Prénoms du salarié (1 à 2, chacun limité à 16 caractères), dans l'ordre de l'état civil. |
worker.sex | string | Si non déductible | "01" homme, "02" femme. |
worker.birth.date | string | Oui | Date de naissance, format YYYY-MM-DD. |
worker.birth.city | string | Si non résoluble | Commune de naissance — libellé (ex. Lyon). |
worker.birth.department | string | Si non déductible | Département de naissance : 01 à 95, 2A/2B (Corse), 971 à 976 (outre-mer), 99 (né à l'étranger). |
worker.birth.country | string | Si non déductible | Pays de naissance — code ISO. Utiliser FR si le département est différent de 99. |
worker.birth.insee_code | string | Non | Code INSEE de la commune de naissance (complément optionnel du libellé). |
worker.nir | string | Oui | NIR du salarié — 13 ou 15 caractères, avec ou sans espaces (2A/2B accepté en Corse). |
worker.nir_key | string | Non | Clé de contrôle du NIR, de 01 à 97. Pesia la calcule si elle est absente. Une clé fournie doit correspondre au NIR. |
worker.address.street | string | Oui | Adresse du salarié — numéro et voie. |
worker.address.postal_code | string | Oui | Code postal (5 chiffres). |
worker.address.city | string | Oui | Commune. |
contract.external_id | string | Oui | Référence unique du contrat / de la mission dans votre organisation et votre environnement. Clé de corrélation de bout en bout (réponses, suivi, webhooks) — même valeur que le mission.contract_external_id de vos lots de paie. |
contract.nature | string | Oui | Nature du contrat : CTT (intérim), CDD ou CDI. |
contract.start_date | string | Oui | Date de début du contrat, format YYYY-MM-DD. |
contract.start_time | string | Oui | Heure d'embauche, format HH:MM:SS. |
contract.end_date | string | CDD | Date de fin du contrat. Requise pour CDD ; doit être absente pour CDI. Facultative pour un CTT : une mission à terme imprécis (remplacement d'un salarié absent, emploi saisonnier) n'en porte pas. Envoyez-la dès qu’elle est connue. |
contract.health_service | string | Non | Code du service de santé au travail (médecine du travail) — format référentiel URSSAF MT + chiffres (ex. MT160). Facultatif pour un contrat CTT (intérim). Par défaut Pesia utilise le service de santé au travail de votre agence ; ne renseignez ce champ que pour surcharger ce défaut sur une mission précise (voir ci-dessous). |
contract.trial_time | string | Non | Durée de la période d'essai, en jours, entier de 1 à 999. Omettre le champ sans période d'essai. |
Service de santé au travail (SST)
Le code du service de santé au travail (médecine du travail) suit le référentiel URSSAF :
format MT suivi de 2 ou 3 chiffres (ex. MT160). Le format historique à 3 chiffres est aussi accepté.
- Contrats
CTT(intérim) — le SST est facultatif : vous n'avez rien à envoyer. C'est le cas de la majorité des intégrations d'agences de travail temporaire. - Contrats
CDDetCDI— le SST est obligatoire : une déclaration sans SST est refusée. Pesia utilise par défaut le service de santé au travail rattaché à votre agence ; si celui-ci n'est pas connu et que vous n'avez pas renseignécontract.health_service, l'élément est retourné en erreurDPAE_HEALTH_SERVICE_REQUIRED(voir Erreurs).
Renseignez contract.health_service uniquement pour surcharger le service de santé au
travail par défaut de l'agence sur une mission donnée. Les codes MT… proviennent du
référentiel officiel des services de santé au travail publié par l'URSSAF (jeu de données
sst_dpae en open data sur open.urssaf.fr).
Champs déduits du NIR et contrôles de cohérence
Un NIR de 13 caractères peut être envoyé seul ; avec 15 caractères, les 2 derniers
caractères sont la clé. Les espaces sont supprimés. Si vous envoyez aussi nir_key,
les deux clés doivent correspondre et être valides.
Pour un NIR qui indique une naissance en France, Pesia complète les champs absents :
sex, selon les informations exploitables du NIR ;birth.department,birth.country: "FR"etbirth.insee_code;birth.city, par recherche du code INSEE dans le référentiel des communes ;nir_key, par calcul.
birth.date reste obligatoire, avec le jour, le mois et l'année complète. Le NIR
permet de contrôler le mois et les deux derniers chiffres de l'année, mais ne donne
ni le jour ni le siècle. Pour une naissance à l'étranger, fournissez le pays réel et
le libellé de la ville. Une donnée ambiguë ou non résoluble doit être fournie : notamment,
un NIR avec un département Corse normalisé 18/19 ne suffit pas à choisir 2A ou 2B.
Exemple de bloc worker avec un NIR de 15 caractères et des champs à compléter par Pesia :
{
"external_id": "MAT-4207",
"last_name": "MARTIN",
"first_names": ["Camille"],
"birth": { "date": "1994-03-12" },
"nir": "294036912322243",
"address": { "street": "12 rue de la République", "postal_code": "69002", "city": "Lyon" }
}
Ce bloc peut remplacer worker dans le premier exemple. La résolution de commune doit
aboutir ; sinon, l'élément porte une erreur explicite. Le NIR de 13 caractères
2940369123222, sans nir_key, produit les mêmes déductions.
Pesia contrôle la cohérence du NIR avec les champs fournis : sexe, mois, année,
département, pays FR pour une naissance en France et code INSEE. Le contrôle tient
compte des mois fictifs et des identifiants provisoires. Le libellé de commune n'est
pas comparé directement au NIR.
Exemple : un NIR qui indique septembre 02 et une date 2003-12-12 produisent cette
erreur dans submissions[].error :
{
"code": "DPAE_NIR_IDENTITY_MISMATCH",
"message": "worker.birth.date : Le mois ou l’année de naissance ne correspond pas au NIR."
}
L'élément porte ok: false et submissionId: null. Son salarié n'est ni créé ni modifié
et sa DPAE n'est pas enregistrée. Les autres éléments valides sont traités, avec un HTTP 202.
Une erreur de structure ou de format détectée avant ce contrôle, dont un NIR ou une
clé invalide, produit un HTTP 400 pour la requête entière. Le traitement par élément
ne commence qu'après cette validation du corps.
Réponse 202 Accepted
Le lot est pris en charge et chaque DPAE acceptée est planifiée pour dépôt. La réponse détaille le résultat élément par élément — le traitement est fail-soft : un échec métier sur un élément ne bloque pas les autres, après validation du corps.
{
"success": true,
"data": {
"mode": "production",
"submissions": [
{
"contractExternalId": "CTT-2026-078451",
"workerExternalId": "MAT-4207",
"submissionId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"status": "SCHEDULED",
"ok": true,
"duplicate": false,
"employeeRegistration": {
"status": "created",
"employeeId": "74dc08aa-c24f-424e-88f0-b0e37438f0a1",
"profileId": "316df07f-7bc9-4cba-92f7-f6f4198e5ac0",
"profileType": "INTERIM"
}
},
{
"contractExternalId": "CTT-2026-078452",
"workerExternalId": "MAT-9001",
"submissionId": "77aa01bc-2d4e-4a8f-b391-c05e7f6a2d18",
"status": "ACK",
"ok": true,
"duplicate": true
},
{
"contractExternalId": "CTT-2026-078453",
"workerExternalId": "MAT-5555",
"submissionId": null,
"status": null,
"ok": false,
"duplicate": false,
"error": { "code": "DPAE_NIR_IDENTITY_MISMATCH", "message": "worker.birth.date : Le mois ou l’année de naissance ne correspond pas au NIR." }
}
]
},
"timestamp": "2026-08-10T12:00:00.000Z"
}
ok: true— l'élément est accepté ;submissionIdidentifie la soumission créée (ou existante).ok: false— l'élément est refusé ;error.codeeterror.messagedétaillent la cause. Corrigez cet élément et re-soumettez-le : les autres éléments du lot ont été traités normalement.duplicate: true— une DPAE est déjà en cours ou acceptée pour cecontract.external_id; la réponse renvoie la soumission existante (voir ci-dessous).
Déduplication : au plus une DPAE active par contrat
Pesia garantit au plus une DPAE active par contract.external_id, dans la même organisation et le même environnement :
- Re-soumettre un contrat dont la DPAE est en cours (
SCHEDULED,SENDING,SENT), conforme (DECLARED) ou acceptée (ACK) renvoieduplicate: trueavec la soumission existante. L'opération est idempotente — aucun double dépôt auprès de l'URSSAF. - Re-soumettre un contrat après un rejet (
REJECTED), un échec (FAILED) ou une annulation (CANCELLED) crée une nouvelle soumission : c'est le mécanisme normal de correction.
Cette déduplication métier est complémentaire de l'idempotence HTTP portée par le header
Idempotency-Key : la clé d'idempotence protège contre le renvoi
accidentel de la même requête (fenêtre 24h), la déduplication par contract.external_id
protège contre un double dépôt du même contrat dans la durée.
Suivre le statut
Par identifiant de soumission
curl https://api.pesia.fr/partner/v1/dpae/submissions/8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37 \
-H "Authorization: Bearer <token>" \
-H "X-Pesia-Env: production"
Réponse 200 OK — la soumission est retournée directement sous data :
{
"success": true,
"data": {
"submissionId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"contractExternalId": "CTT-2026-078451",
"agencySiret": "83123456700045",
"status": "ACK",
"scheduledAt": null,
"sentAt": "2026-07-11T09:05:12Z",
"declaredAt": "2026-07-11T09:18:44Z",
"arReceivedAt": "2026-07-11T09:20:00Z",
"rDossier": "DOSSIER-EXEMPLE",
"bisReceivedAt": null,
"acknowledgedAt": null,
"identity": null,
"employeeRegistration": {
"status": "created",
"employeeId": "74dc08aa-c24f-424e-88f0-b0e37438f0a1",
"profileId": "316df07f-7bc9-4cba-92f7-f6f4198e5ac0",
"profileType": "INTERIM"
}
},
"timestamp": "2026-08-10T12:00:00.000Z"
}
Par référence de contrat
curl "https://api.pesia.fr/partner/v1/dpae/submissions?contractExternalId=CTT-2026-078451" \
-H "Authorization: Bearer <token>" \
-H "X-Pesia-Env: production"
Cette variante retourne l'historique des tentatives pour ce contrat, les plus récentes d'abord — utile après un rejet pour retrouver la soumission de correction et les précédentes.
Réponse 200 OK — une collection : les soumissions sont sous data.items, accompagnées
d'un bloc data.meta (total = nombre de soumissions retournées, page: 1, limit = taille
de la liste) :
{
"success": true,
"data": {
"items": [
{
"submissionId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"contractExternalId": "CTT-2026-078451",
"agencySiret": "83123456700045",
"status": "ACK",
"scheduledAt": null,
"sentAt": "2026-07-11T09:05:12Z",
"declaredAt": "2026-07-11T09:18:44Z",
"arReceivedAt": "2026-07-11T09:20:00Z",
"rDossier": "DOSSIER-EXEMPLE",
"bisReceivedAt": null,
"acknowledgedAt": null,
"identity": null,
"conformityCertificate": "CERTIFICAT-EXEMPLE",
"errorMessage": null,
"sourceSubmissionId": null,
"correctedAt": null
},
{
"submissionId": "2c7e9a3b-4d1f-4e6a-8b5c-0d3f7a9e1c24",
"contractExternalId": "CTT-2026-078451",
"agencySiret": "83123456700045",
"status": "REJECTED",
"scheduledAt": null,
"sentAt": "2026-07-10T09:04:47Z",
"declaredAt": null,
"arReceivedAt": null,
"rDossier": null,
"bisReceivedAt": null,
"acknowledgedAt": null,
"identity": null,
"errorMessage": "Code URSSAF invalide",
"conformityCertificate": null
}
],
"meta": { "total": 2, "page": 1, "limit": 2 }
},
"timestamp": "2026-08-10T12:00:00.000Z"
}
agencySiret: SIRET de l'établissement déclarant, dérivé de l'agence.- Les dates sont au format ISO 8601, en UTC, et peuvent être
null. scheduledAtn'est actuellement pas renseigné. Ne l'utilisez pas comme heure d'envoi prévue.sentAtdate l'envoi ;declaredAtdate la réception du certificat de conformité positif.arReceivedAtdate le résultat AR individuel, positif ou négatif.rDossiercontient la référence dossier URSSAF. Un AR positif confirme l'enregistrement.bisReceivedAtdate le BIS éventuel.identitycontient son résultat et les corrections proposées.acknowledgedAtest déprécié. Il reste l'alias historique debisReceivedAt, jamais dearReceivedAt. Une DPAE enregistrée peut donc avoiracknowledgedAt: nulletidentity: null.
La liste exige contractExternalId ; elle n'accepte pas de filtre agencyCode.
Un historique vide renvoie items: [] et meta: { total: 0, page: 1, limit: 1 }.
Le suivi GET et l’historique par contrat exposent errorMessage (motif assaini) et
conformityCertificate (texte du certificat CCO). Ces champs peuvent être absents ou null
sur les anciennes données. Le suivi public n’expose pas de clé de stockage ni de rapport brut.
Une nouvelle version porte sourceSubmissionId. Une correction porte aussi correctedAt.
En cas de rejet ou de blocage, contactez partenaires@pesia.fr
avec l'environnement, le submissionId et votre contractExternalId.
Cycle de vie des statuts
| Statut | Signification | Action recommandée |
|---|---|---|
SCHEDULED | Soumission en attente d'envoi. | Suivez son avancement. Le HTTP 202 ne garantit pas l'heure d'envoi. |
SENDING | Envoi vers l'URSSAF en cours. | Attendez. L'annulation est déjà refusée. |
SENT | Transmission effectuée, sans verdict métier final. | Attendez un retour URSSAF. |
DECLARED | Certificat de conformité positif reçu. | Continuez le suivi individuel. |
ACK | AR individuel positif : embauche enregistrée. | Conservez rDossier. N’attendez pas un BIS. |
REJECTED | Retour négatif URSSAF associé à cette soumission. | Consultez errorMessage. Vérifiez le résultat avant une nouvelle tentative. |
FAILED | Échec de la chaîne d’envoi ou de traitement, y compris un avis de rejet d’envoi URSSAF (ARE). | Contactez Pesia avant une nouvelle tentative si le résultat de l'envoi est incertain. |
CANCELLED | Annulation confirmée avant envoi. | Une nouvelle soumission du contrat est possible. |
Les retours peuvent arriver dans un ordre différent : ACK peut être atteint sans
passage observable par DECLARED. Un retour absent, partiel ou non corrélable ne vaut
ni acceptation ni rejet. Aucun délai de verdict n'est garanti par ces statuts.
Enregistrement et identité : deux suivis indépendants
La DPAE est enregistrée à réception de son AR individuel positif. Le BIS ne conditionne pas cet enregistrement.
Un HTTP 202, un écho de dépôt ou un accusé technique ne constitue pas cet AR.
Le CCO certifie la conformité ; l'AR confirme l'enregistrement ; le BIS traite l'identité.
Le BIS est éventuel : son absence ne prouve ni une anomalie ni une validation d'identité.
Le diagramme présente les responsabilités, sans garantir l'ordre des retours.
Un BIS reçu avant l'AR conserve SENT ou DECLARED. Un BIS reçu après l'AR conserve ACK,
y compris pour NOT_IDENTIFIED. Il ne déclenche ni rejet DPAE ni nouveau dépôt.
Un CCO tardif complète le certificat sans rétrograder ACK.
Parcours d'intégration partenaire
- Conservez
submissionIdet votre référence contrat après le POST. - Suivez l'enregistrement avec
status,arReceivedAtetrDossier. N'attendez pasbisReceivedAt. - À réception de
dpae.identity_checked, relisez la soumission avec le même tenant, organisation et environnement. - Pour
MODIFIED, comparez les valeurs non nulles deidentity.correctionsavec vos justificatifs. Un champ nul signifie qu'aucune correction n'est fournie pour ce champ ; ne videz pas votre donnée. - Pour
NOT_IDENTIFIED, vérifiez l'identité et contactez Pesia si nécessaire. Ne redéposez pas une DPAE enregistrée pour ce seul motif. - Conservez le résultat et appliquez les corrections vérifiées à votre référentiel salarié, puis aux déclarations suivantes. La réception du BIS ne modifie pas automatiquement vos données.
Extrait d'un GET après AR positif puis BIS avec proposition de correction, avec des données fictives :
{
"status": "ACK",
"arReceivedAt": "2026-07-11T09:20:00Z",
"rDossier": "DOSSIER-EXEMPLE",
"bisReceivedAt": "2026-07-12T04:10:03Z",
"acknowledgedAt": "2026-07-12T04:10:03Z",
"identity": {
"result": "MODIFIED",
"corrections": {
"nir": null,
"surname": "NOM EXEMPLE",
"givenNames": null,
"birthDate": null
}
}
}
Les mêmes champs figurent dans l'historique par contrat. Les corrections nominatives sont réservées
à la lecture authentifiée. Elles ne figurent pas dans le webhook et ne doivent pas être recopiées dans vos logs.
errorMessage décrit le rejet ou l'échec DPAE ; consultez identity.result pour le résultat SNGI.
Compatibilité et anciennes données
Les nouveaux champs sont optionnels et nullables. Migrez vos lecteurs avant de vous abonner
à dpae.identity_checked. Conservez le traitement des anciens messages et dédupliquez par eventId.
La signification historique de acknowledgedAt ne change pas. Aucun ancien webhook n'est réémis automatiquement.
Les anciens traitements pouvaient produire ACK depuis un BIS. Pour une ancienne soumission ACK
sans arReceivedAt ni rDossier, demandez la preuve d'enregistrement à Pesia. Ne déduisez pas une preuve AR
de ce seul statut et ne redéposez pas automatiquement. Un AR réellement reçu peut compléter cette ancienne donnée.
Les anciens résultats négatifs ne sont pas réécrits automatiquement. Un ancien errorMessage peut encore contenir un diagnostic BIS ; il ne remplace pas la preuve AR.
La FAQ officielle DPAE de l'URSSAF distingue l'AR et le BIS éventuel. Le guide d'identification Net-entreprises précise la vérification des écarts d'identité. Un écart peut aussi nécessiter une correction auprès de la caisse.
Annuler une DPAE (avant envoi)
L'annulation est disponible tant que la soumission est SCHEDULED et que l'envoi n'a
pas commencé. Sa confirmation 200 avec CANCELLED garantit qu'elle ne sera pas envoyée.
Une lecture préalable de SCHEDULED ne réserve pas cette possibilité : l'envoi peut
commencer entre votre lecture et votre demande. Il n'existe pas de délai minimal garanti
pour annuler.
curl -X POST https://api.pesia.fr/partner/v1/dpae/submissions/8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37/cancel \
-H "Authorization: Bearer <token>" \
-H "Idempotency-Key: 5b2c8d1e-6f3a-4b7c-9d0e-1a2b3c4d5e6f" \
-H "X-Pesia-Env: production"
Le header Idempotency-Key est obligatoire (comme sur tout POST).
Réponse 200 OK — la soumission passe au statut CANCELLED :
{
"success": true,
"data": {
"submissionId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"contractExternalId": "CTT-2026-078451",
"agencySiret": "83123456700045",
"status": "CANCELLED",
"scheduledAt": null,
"sentAt": null,
"declaredAt": null,
"acknowledgedAt": null
},
"timestamp": "2026-08-10T12:00:00.000Z"
}
Après annulation, le contract.external_id redevient disponible : vous pouvez re-soumettre
une nouvelle DPAE pour ce contrat si besoin.
Si l’envoi a commencé ou si la soumission ne peut plus être annulée (notamment SENDING, SENT, DECLARED, ACK, REJECTED ou FAILED),
l'annulation est refusée avec un 409 (DPAE_NOT_CANCELLABLE) :
{
"type": "https://docs.pesia.fr/partner/errors/DPAE_NOT_CANCELLABLE",
"title": "Conflict",
"status": 409,
"detail": "Cette DPAE est déjà transmise à l'URSSAF (ou dans un état terminal) et ne peut plus être annulée.",
"code": "DPAE_NOT_CANCELLABLE",
"instance": "/partner/v1/dpae/submissions/8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37/cancel",
"timestamp": "2026-08-10T12:00:00.000Z"
}
En cas de 409, consultez le statut courant. Pour une correction après envoi ou une
situation particulière, contactez partenaires@pesia.fr.
Notifications webhook
Plutôt que d'interroger l'API en boucle, abonnez-vous aux événements DPAE — voir Webhooks pour la signature HMAC, les headers de livraison et la politique de retry :
curl -X POST https://api.pesia.fr/partner/v1/webhooks/subscriptions \
-H "Authorization: Bearer <token>" \
-H "Idempotency-Key: 7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f" \
-H "X-Pesia-Env: production" \
-H "Content-Type: application/json" \
-d '{"endpointUrl": "https://webhooks.example.com/pesia", "eventTypes": ["dpae.declared", "dpae.acknowledged", "dpae.rejected", "dpae.identity_checked"]}'
Abonnez-vous aux événements de déclaration et au résultat d’identité :
| Statut atteint | Événement |
|---|---|
DECLARED | dpae.declared |
ACK | dpae.acknowledged |
REJECTED / FAILED | dpae.rejected (champ status pour les distinguer) |
| Statut conservé, BIS reçu | dpae.identity_checked (champ identityResult) |
Pesia conserve les événements DPAE à publier et reprend leur publication après une
indisponibilité temporaire. Le délai de notification peut donc dépasser celui du verdict.
Un événement conserve son eventId, son occurredAt et son contenu lors des nouvelles tentatives.
La livraison peut être répétée et son ordre n'est pas garanti. N'attendez pas exactement
deux notifications de succès : un AR peut produire ACK avant un certificat de conformité.
Un BIS produit dpae.identity_checked, jamais dpae.acknowledged.
En cas de doute, relisez le statut courant via GET, dans le même environnement.
Une annulation (
POST /partner/v1/dpae/submissions/{id}/cancel) est confirmée de façon synchrone dans la réponse200 OKde l'appel — elle n'émet aucun événement webhook. N'attendez donc pas de notification pour une DPAE que vous annulez : le statutCANCELLEDvous est déjà renvoyé par l'appel d'annulation.
BAN et revue des retours
Un BAN attribué à votre soumission produit REJECTED et le webhook dpae.rejected.
Consultez errorMessage pour le code et le motif URSSAF.
Un CCO partiel ne prouve pas la conformité de toutes les soumissions du dépôt.
Le GET expose aussi reviewRequired et reviewReason.
Si reviewRequired vaut true, demandez la revue du retour avant tout redépôt.
Une tentative de redépôt répond ok: false, duplicate: true et DPAE_REVIEW_REQUIRED.
Le statut conserve le dernier verdict acquis.
Ces champs peuvent être absents pendant la mise à jour des services.
Exemple de réponse partielle après un rejet attribué :
{
"status": "REJECTED",
"errorMessage": "Rejet URSSAF — code 46 : date de fin invalide ou antérieure à l’embauche.",
"reviewRequired": false,
"reviewReason": null
}
Corrigez le payload puis créez une nouvelle soumission avec la même référence de contrat et une nouvelle Idempotency-Key.
Le BO Pesia donne accès au BAN source. Le GET partenaire ne fournit pas de clé de stockage.
Une création accepte une date de début de J−7 à J+7 inclus, selon Europe/Paris.
Une correction dont le serveur retrouve la soumission antérieure conserve la fenêtre de ±1 an.
La date de fin, si elle est présente, doit être supérieure ou égale à la date de début.
La naissance doit être une date calendaire réelle, non future selon Europe/Paris et strictement antérieure au début du contrat.
Ces contrôles valent aussi pour une correction. Le mois et l’année restent comparés au NIR ; le siècle n’est jamais déduit.
Une date impossible peut être refusée dès la validation du corps avec HTTP 400, avant le résultat par élément.
Par exemple, 1985-04-31 est refusé. 2000-02-29 est valide si le NIR est cohérent et si le contrat commence après cette date.
dpae.declared — DPAE conforme
Les références communes sont complétées par conformityCertificate. Cet événement ne contient pas les champs de preuve AR.
Un CCO reçu après un AR complète le certificat et peut émettre cet événement sans rétrograder ACK.
Le premier certificat reste la preuve conservée. Un autre certificat ne le remplace pas automatiquement. Routez sur eventType et
réutilisez le même code de lecture.
dpae.acknowledged — AR individuel positif
{
"eventType": "dpae.acknowledged",
"eventId": "b1e4a7d0-3c5f-4e2a-8d9b-6f1c0a7e5b42",
"occurredAt": "2026-07-12T04:10:03Z",
"tenantId": "01a08af4-d5c0-735f-bcd5-2e17f00b873d",
"organizationId": "01a08af4-d5f8-70bb-b8b9-df37692cbd9a",
"env": "production",
"dpaeId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"agencySiret": "83123456700045",
"contractExternalId": "CTT-2026-078451",
"arReceivedAt": "2026-07-12T04:10:03Z",
"rDossier": "DOSSIER-EXEMPLE"
}
dpae.identity_checked — résultat BIS
L'événement contient les références communes et identityResult (IDENTIFIED, MODIFIED ou NOT_IDENTIFIED).
Il ne contient ni NIR ni nom ni correction. Consultez le flux webhook.
Il ne remplace pas dpae.corrected, qui annonce une nouvelle version corrigée de DPAE.
dpae.rejected — DPAE rejetée ou en échec
Les références communes sont complétées par un champ status qui distingue le rejet URSSAF (REJECTED)
de l’échec d’envoi ou de traitement (FAILED, qui inclut les ARE). errorMessage donne le motif assaini :
{
"eventType": "dpae.rejected",
"eventId": "d9f2c5b8-1a4e-4f7c-a3d6-8b0e2c5f9a17",
"occurredAt": "2026-07-12T04:10:03Z",
"tenantId": "01a08af4-d5c0-735f-bcd5-2e17f00b873d",
"organizationId": "01a08af4-d5f8-70bb-b8b9-df37692cbd9a",
"env": "production",
"dpaeId": "8f2d4c1a-5b3e-4f7a-9c2d-1e6b8a4f0d37",
"agencySiret": "83123456700045",
"contractExternalId": "CTT-2026-078451",
"status": "REJECTED",
"errorMessage": "Bilan d’anomalie bloquant (BAN): code URSSAF invalide"
}
dpaeIdreprend lesubmissionIdretourné lors du dépôt.- La livraison est at-least-once : dé-dupliquez sur
eventId, stable entre re-tentatives.
dpae.corrected — nouvelle version créée par Pesia
Abonnez-vous à dpae.corrected pour suivre une correction du staff.
Cet événement indique la création d’une nouvelle soumission, sans promesse d’acceptation URSSAF.
dpaeId est la nouvelle soumission. sourceSubmissionId est la source conservée.
Les champs communs incluent eventId, occurredAt, tenantId, organizationId, env,
agencySiret et contractExternalId. Aucun NIR, snapshot ou motif interne n’est transmis.
Consultez la nouvelle soumission avec GET et continuez son suivi normal.
Sandbox
Avec un accès sandbox et le header X-Pesia-Env: sandbox, Pesia transmet la DPAE à
l'URSSAF en mode de validation, sans enregistrer une embauche réelle.
Testez la structure du corps, les erreurs par élément, les champs déduits du NIR,
l'idempotence et les retours de conformité. SENT ne suffit pas à valider le dépôt.
Un retour non corrélable à une embauche ne produit pas un rejet collectif supposé.
Les retours disponibles en validation ne constituent pas une garantie de reproduction de tous les contrôles de production. Ne conditionnez pas la réussite de votre parcours sandbox à un BIS ou à un délai fixe. Testez aussi votre récepteur local avec les exemples de notifications, dont les doublons et les livraisons dans un ordre différent. Voir Sandbox pour les identifiants et l'isolation des environnements.
Erreurs
Les erreurs HTTP suivent le format application/problem+json (RFC 7807), comme le
reste de l'API. Le champ code est stable et destiné au traitement programmatique ;
detail est un message lisible :
{
"type": "https://docs.pesia.fr/partner/errors/DPAE_MANDATE_MISSING",
"title": "Unprocessable Entity",
"status": 422,
"detail": "Mandat de déclaration URSSAF non actif pour l'agence — contactez votre interlocuteur Pesia.",
"code": "DPAE_MANDATE_MISSING",
"instance": "/partner/v1/dpae/submissions",
"timestamp": "2026-08-10T12:00:00.000Z"
}
| Statut HTTP | Cause | Action recommandée |
|---|---|---|
400 | Corps invalide (champ manquant ou mal formé, lot vide ou > 200 éléments). | Corrigez la requête à partir du détail fourni dans la réponse. |
400 | Profil déclarant de l'agence incomplet. | Contactez votre interlocuteur Pesia pour compléter le profil déclarant de l'agence. |
400 | idempotency_key_required / idempotency_key_invalid_format. | Fournissez un header Idempotency-Key au format UUIDv4 ou ULID. |
403 | insufficient_scope. | Le scope dpae:write manque à votre grant — voir Scopes. |
404 | Agence introuvable, ou soumission absente de votre organisation et de votre environnement. | Vérifiez le champ code retourné par GET /partner/v1/agencies, ou l'identifiant de soumission. |
409 | idempotency_key_conflict — même clé réutilisée avec un corps différent. | Générez une nouvelle Idempotency-Key par lot distinct. |
409 | DPAE_NOT_CANCELLABLE — annulation demandée pendant ou après l’envoi d’une DPAE à l'URSSAF (ou terminale). | Consultez le statut courant. Voir Annuler une DPAE. |
422 | DPAE_MANDATE_MISSING — mandat de déclaration URSSAF non actif pour cette agence. | Contactez votre interlocuteur Pesia (partenaires@pesia.fr). |
503 | DPAE_UPSTREAM_UNAVAILABLE — service de déclarations momentanément indisponible. | Consultez l’historique du contrat, puis réessayez avec la même clé et le même corps. |
Les erreurs par élément n'empêchent pas le traitement du reste du lot : elles sont
retournées dans la réponse 202 avec ok: false (voir
Réponse 202) :
DPAE_INVALID_WORKER— identité du salarié invalide lors du traitement métier. Le message nomme les champs en cause, jamais leurs valeurs. Corrigez l'élément et re-soumettez-le.DPAE_NIR_IDENTITY_MISMATCH— contradiction entre le NIR et les données d'identité fournies.DPAE_EMPLOYEE_IDENTITY_INCOMPLETE— identité incomplète après déduction. Fournissez les champs indiqués.DPAE_BIRTH_COMMUNE_UNAVAILABLE— recherche de commune indisponible. Réessayez plus tard ou fournissez le libellé correct.DPAE_DUPLICATE_IN_BATCH— le mêmecontract.external_idapparaît plusieurs fois dans le même lot. Ne soumettez chaquecontract.external_idqu'une seule fois par requête.DPAE_CTT_REQUIRES_NAF_7820Z— un contrat CTT exige le code NAF employeur7820Z.DPAE_START_DATE_OUT_OF_RANGE— la date d’embauche dépasse J−7 à J+7 à la création, ou ±1 an pour une correction liée à une soumission antérieure.DPAE_BIRTH_DATE_INVALID— date de naissance impossible.DPAE_BIRTH_DATE_IN_FUTURE— naissance postérieure au jour courant en Europe/Paris.DPAE_BIRTH_DATE_NOT_BEFORE_START— naissance le jour du début du contrat ou après.DPAE_REVIEW_REQUIRED— un retour URSSAF ambigu ou contradictoire bloque le redépôt. ConsultezreviewReason.DPAE_HEALTH_SERVICE_REQUIRED— contratCDD/CDIsans service de santé au travail résoluble (voir Service de santé au travail). Ne concerne pas les contratsCTT.DPAE_INTERNAL_ERROR— erreur interne pendant le traitement de l'élément. Contactez Pesia.
Corrigez et renvoyez les éléments refusés avec une nouvelle clé d'idempotence. Pour répéter la même requête après une coupure réseau, conservez sa clé et son corps. Un échec HTTP après le début du traitement ne garantit pas qu'aucune autre agence du lot n'a été prise en charge : consultez l'historique par contrat avant de créer une nouvelle tentative.
Les messages destinés aux partenaires ne reprennent pas le NIR du salarié.
Le champ errorMessage du suivi GET décrit le résultat asynchrone.
Les erreurs par élément du POST restent distinctes de ce verdict.
Voir aussi
- Scopes — scope
dpae:write - Idempotence — header
Idempotency-Key - Lots de paie — soumettre les missions des mêmes contrats pour le calcul des bulletins
- Webhooks — abonnements, signature HMAC, retry
- Sandbox — environnement de test