Rôles & Permissions
Chaque Freight Document associe plusieurs rôles (parties prenantes) : CONSIGNOR (expéditeur), CARRIER (transporteur), CONSIGNEE (destinataire), PLACEOFTAKINGOVER/PLACEOFDELIVERY (lieux physiques de collecte/livraison, potentiellement distincts des parties contractuelles), SUBSEQUENTCARRIER (transporteur relais), SUBCONTRACTOR.
Chaque rôle porte un ensemble de permissions par défaut (consultation, changement de statut, modification de certains champs). Votre réponse à GET /v1/freightdocuments/{id} inclut toujours un champ ownPermissions, reflétant ce que vous êtes autorisé à faire sur ce document précis, recalculé à chaque appel.
Identifier une partie : account_id ou email
Chaque rôle (hors SUBMITTER) est identifié par l'un des deux : account_id, si la partie a déjà un compte, ou email sinon. Ces deux modes ne sont pas interchangeables : email sert uniquement le cas "cette partie n'a pas encore de compte" — le rôle s'y rattache automatiquement le jour où un compte avec cet email s'active, mais jamais avant, même si un compte avec cet email existe déjà au moment de la création du rôle. Pour cibler une partie qui a déjà un compte, utilisez toujours account_id — résolu à partir de son email via GET /v1/accounts/lookup?email=... si vous ne connaissez pas déjà son identifiant (voir Référence API). C'est exactement le choix que fait ecmr-platform (console web) sur son formulaire de création de document : jamais d'UUID demandé à l'utilisateur, une recherche par email en mode "Compte existant".
L'exception : les deux rôles de lieu
PLACEOFTAKINGOVER et PLACEOFDELIVERY peuvent être créés sans aucun des deux. Un quai de chargement n'est pas une entreprise avec une boîte aux lettres : ces deux rôles sont identifiés par leur adresse, et exiger un email y poussait à en inventer une — or une adresse inventée devient silencieusement la clé de rattachement décrite ci-dessus.
Ce que ça coûte, et c'est définitif : un rôle de lieu créé sans email ni account_id ne pourra jamais signer. La cérémonie de signature résout le signataire depuis account_id (voir Signature électronique) ; un email n'est pas un moyen de signer, seulement la promesse d'un account_id futur. Et rien ne permet d'ajouter un identifiant à un rôle après la création du document.
Concrètement : si vous voulez que le lieu d'enlèvement signe lui-même la prise en charge, donnez-lui un account_id ou un email. Si l'enlèvement est signé par le transporteur ou par votre propre entrepôt, un lieu sans identifiant est le choix juste — il reste nommé sur le document par son adresse.
Identité fiscale : vat_number et nif
Chaque rôle qui représente une entité juridique — CONSIGNOR, CONSIGNEE, CARRIER, SUBSEQUENTCARRIER, SUBCONTRACTOR — porte son identité fiscale dans son party_snapshot (ou la tient de la fiche d'annuaire dont il est issu) :
| Champ | Quand il est exigé | Validation |
|---|---|---|
vat_number |
Toujours | Forme seulement : préfixe pays de 2-3 lettres, puis 2 à 20 caractères alphanumériques. Jamais vérifié contre un registre réel. |
nif |
Seulement si address.country vaut ES |
Stricte, caractère de contrôle compris : DNI (8 chiffres + lettre), NIE (X/Y/Z + 7 chiffres + lettre) ou CIF (lettre + 7 chiffres + caractère de contrôle). |
Le NIF n'est exigé que d'une partie établie en Espagne, et c'est délibéré : un CMR est un document international, et une partie française a un SIREN, jamais de NIF. Le contrôle du NIF est en revanche strict, à la différence de tout le reste de l'API — parce que la valeur est figée sur le document et qu'aucun endpoint ne permet de la corriger ensuite.
Les deux rôles de lieu ne sont jamais concernés : un quai de chargement n'a pas d'identité fiscale.
C'est une règle métier Fincargo pour le marché espagnol, pas une exigence de la Convention CMR.
Identité figée d'une partie : party_snapshot
Quand un rôle est saisi manuellement (pas via partner_id), party_snapshot fige son identité au moment de l'assignation — name (requis) et, optionnellement, address. address est structuré, pas un texte libre : {street, postal_code, city, country}, les 4 champs requis dès qu'une adresse est fournie (country : code à 2 lettres type ISO 3166-1 alpha-2, ex. "ES" — vérifié uniquement sur la forme, jamais contre une liste de codes réels). Un objet incomplet est rejeté (freight_document.invalid_address) ; ne pas fournir address du tout reste parfaitement valide.
party_snapshot accepte aussi une clé gln (optionnel) — le GLN GS1 (Global Location Number) de la partie, exactement 13 chiffres, vérifié uniquement sur la forme, rejeté avec freight_document.invalid_gln sinon. Via partner_id, c'est le gln du Partner (annuaire) qui est figé automatiquement — voir Annuaire.
{
"name": "Acme Consignor SL",
"address": { "street": "Calle Mayor 1", "postal_code": "28013", "city": "Madrid", "country": "ES" }
}
Cette même structure s'applique à Partner.address (annuaire, voir Annuaire) — un rôle créé via partner_id hérite donc de la même forme automatiquement.
Comptes "site" et sous-comptes
Un rôle peut être porté par un compte représentant une organisation (par exemple un entrepôt), qui délègue en interne à plusieurs employés (sous-comptes) — utile quand plusieurs personnes peuvent légitimement agir pour un même rôle selon qui est de service, sans qu'il soit nécessaire de désigner une personne précise à l'avance.
Ciblage optionnel d'un sous-compte précis — par défaut, tous les sous-comptes du compte porteur du rôle héritent d'un accès identique à ce document. Si votre intégration a besoin de restreindre l'accès à un seul sous-compte précis (par exemple : ne notifier/autoriser qu'un chauffeur précis plutôt que toute l'entreprise), PATCH /v1/freightdocuments/{id}/roles/{roleId}/assign-subaccount (corps { "subaccount_id": "..." }, ou null pour revenir à l'accès global) permet de le faire. Le compte porteur du rôle lui-même n'est jamais affecté — seuls les autres sous-comptes perdent l'accès une fois un ciblage actif. Réservé au titulaire d'origine du rôle (pas un délégataire, voir ci-dessous) ; subaccount_id doit appartenir au même compte, sinon freight_document.subaccount_not_eligible.
Provisionner un sous-compte : création directe ou auto-inscription
Si votre intégration gère elle-même le cycle de vie de vos chauffeurs (plutôt que de passer par l'espace "Paramètres" → "Chauffeurs" d'ecmr-platform), deux méthodes coexistent sur POST /v1/accounts/me/subaccounts — vous choisissez l'email et le mot de passe vous-même, à communiquer au chauffeur hors bande — et une nouvelle, POST /v1/accounts/me/subaccounts/invite, où c'est le chauffeur qui termine sa propre inscription via un lien.
L'invitation prend un channel (SMS ou EMAIL) :
SMS: vous ne fournissez quedisplay_nameetphone_number(E.164, ex."+33612345678"— validé sur ce champ précis, à la différence de la plupart des autres champsphone_numberde l'API). Le chauffeur reçoit un lien par SMS, choisit lui-même son email et son mot de passe en l'ouvrant. Recevoir ce lien constitue à lui seul la preuve que ce numéro lui appartient — aucune étape supplémentaire n'est demandée.EMAIL: vous fournissez en plusemail(qui devient l'email de connexion définitif, jamais redemandé). Le chauffeur reçoit le lien par email, mais doit en plus vérifier son numéro de téléphone par un code SMS avant de pouvoir choisir un mot de passe — rien ne prouve encore que ce numéro est le sien tant que le lien n'a transité que par email.
Dans les deux cas, une fois l'inscription complétée, le sous-compte porte phone_verified: true — exposé sur GET /v1/subaccounts/me et sur chaque réponse de l'API sous-comptes. C'est ce champ, pas la simple présence de phone_number, qui conditionne certains raccourcis de préremplissage côté ecmr-app (voir Expérience terrain) : un numéro que vous auriez renseigné vous-même sans passer par l'invitation reste phone_verified: false.
Un lien d'invitation expire (account.invitation_token_expired) après un délai de plusieurs jours ; POST /v1/accounts/me/subaccounts/{id}/invitations/resend en génère un nouveau et invalide immédiatement l'ancien. Codes d'erreur dédiés : voir Codes d'erreur.
Modifier le champ references du document : UPDATE_ROLE_REFERENCE
Sur PATCH /v1/freightdocuments/{id}, modifier le champ references du document (les références libres type customer_order_ref) exige la permission UPDATE_ROLE_REFERENCE — réservée à SUBMITTER, CONSIGNOR, CONSIGNEE et CARRIER. Les rôles de lieu (PLACEOFTAKINGOVER/PLACEOFDELIVERY), SUBSEQUENTCARRIER et SUBCONTRACTOR n'ont pas cette permission ; les autres champs du PATCH exigent seulement UPDATE (ou CHANGE_STRUCTURED_GOODS pour goods_lines).
Délégation vers un tiers externe
Un rôle peut aussi être délégué vers une autre organisation — le cas typique étant la sous-traitance de transport. Seuls CARRIER, SUBSEQUENTCARRIER et SUBCONTRACTOR peuvent déléguer (permission DELEGATE) ; un CONSIGNOR, CONSIGNEE ou rôle de lieu ne le peut pas. Voir Sous-traitance avec TMS et sans TMS pour le détail des mécanismes.
Le délégataire dispose du même mécanisme de ciblage, de façon indépendante et symétrique : PATCH /v1/freightdocuments/{id}/roles/{roleId}/delegations/{delegationId}/assign-subaccount restreint l'accès hérité de cette délégation précise à un seul sous-compte du délégataire, sans jamais affecter le ciblage (ou l'absence de ciblage) posé côté rôle d'origine. Réservé au titulaire exact de cette délégation (delegate_account_id) — pas au délégateur, ni à un autre membre de la chaîne.
Pièces jointes scellées
SUBMITTER, CONSIGNOR, CONSIGNEE et les rôles de lieu (PLACEOFTAKINGOVER/PLACEOFDELIVERY) voient les pièces jointes marquées sealed. CARRIER, SUBSEQUENTCARRIER et SUBCONTRACTOR ne les voient pas du tout — l'idée n'est pas seulement de bloquer le téléchargement, une pièce scellée est absente de la liste elle-même pour ces rôles. Voir Pièces jointes & PDF.