FR EN

Enregistrer un consentement hors ligne

Toutes les personnes concernées n'ont pas de clé d'accès. Une personne âgée qui signe un formulaire sur papier, ou qui répond au téléphone, ne passera jamais par le flux d'approbation par demande de consentement. Pour ces cas, l'organisation consigne elle-même le consentement, par l'une de deux voies :

  • Sur papier : portée attest, palier manual, assurance company_attested. La preuve est une feuille signée à la main, dont l'empreinte est consignée.
  • Par téléphone : portée attest_verbal, palier verbal, assurance company_documented. La preuve est la parole de l'organisation : il n'y a aucun document.

Les deux autorisent à /v1/check exactement comme un consentement signé par le citoyen; seuls tier et assurance diffèrent, et c'est votre système qui décide de ce que chaque palier débloque. La portée attest_verbal n'est jamais cochée par défaut sur une clé : elle doit être un choix délibéré.

Choisir la version du document

Chaque consentement hors ligne se rattache à la version publiée exacte d'un document de consentement, son documentVersionId. Lisez-la avec GET /v1/consent-documents, ou avec GET /v1/catalog?documentCode=..., qui renvoie du même coup les cellules à présenter.

La personne doit recevoir le texte de cette version. Le document d'information se télécharge en PDF, à imprimer avec la feuille ou seul :

curl -sS "https://api.agreely.ca/v1/consent-documents/versions/$VERSION_ID/pdf?locale=fr" \
  -H "Authorization: Bearer $AGREELY_API_KEY" -o document-information.pdf

Télécharger ce PDF ne consigne rien : ce n'est pas une preuve que la personne a été informée.

Sur papier

Il vous faut une clé à portée attest.

Imprimer la feuille de signature

POST /v1/customers/{customerRef}/consent-sheets produit la feuille de signature d'une version pour un client que l'organisation connaît : une paire Oui/Non par demande de consentement, les finalités d'information sans case, la signature et une référence imprimée. Le même appel émet le lien de réclamation dont cette référence est le second facteur.

curl -sS https://api.agreely.ca/v1/customers/cust_8812/consent-sheets \
  -H "Authorization: Bearer $AGREELY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: feuille-cust_8812-2026-10-09" \
  -d '{"documentVersionId":"e4d41dc3-c8a5-44b1-96c5-be740c45cc6d","locale":"fr"}'
# { "signatureSheet": { "pdf": "<base64>", ... }, "printedReference": "ABCD-EFGH", "claim": { "claimUrl": "...", ... } }

La référence et le lien ne sont renvoyés qu'une fois : conservez-les au moment de l'appel. Une nouvelle feuille pour le même client retire le lien précédent.

Deux règles avec une feuille de signature

N'envoyez jamais le lien de réclamation dans la même enveloppe que la feuille, ni dans le même message. La référence imprimée ne protège qu'un lien qui voyage séparément.

N'envoyez jamais l'empreinte de la feuille vierge comme evidence.pdfSha256. La preuve est la feuille signée, numérisée à son retour : c'est son empreinte qu'on consigne à l'étape suivante.

Consigner la feuille signée

Vous partez de la feuille signée, numérisée en PDF, et de la version publiée sous laquelle la personne a consenti. Le SDK hache le PDF localement (SHA-256); par défaut, seul le pdfSha256 quitte votre machine. Les octets bruts ne partent qu'avec une mise sous séquestre explicite.

const m = await agreely.manualConsents.record({
  customerId: "cust_8812",
  documentVersionId: "doc_v3",     // the PUBLISHED disclosure version signed under
  effectiveDate: "2026-01-01",
  validUntil: "2031-01-01",
  items: [{ category: "Phone number", purpose: "Billing" }],
  evidence: {
    pdfSha256: Agreely.hashPdf(bytes), // "0x"+sha256, hashed LOCALLY, required
    // pdf: base64Pdf,                 // optional: only with an explicit upload
  },
});

m.assurance;   // "company_attested"
m.consentRefs; // one 0x ref per cell; m.anchored is false at record time
$m = $agreely->manualConsents()->record([
    'customerId'        => 'cust_8812',
    'documentVersionId' => 'doc_v3',
    'effectiveDate'     => '2026-01-01',
    'validUntil'        => '2031-01-01',
    'items'             => [['category' => 'Phone number', 'purpose' => 'Billing']],
    'evidence'          => [
        'pdfSha256' => Agreely::hashPdf($bytes), // "0x"+sha256, LOCAL, required
        // 'pdf'    => $base64Pdf,               // optional opt-in upload
    ],
]);

$m->assurance;   // "company_attested"
$m->consentRefs; // one 0x ref per cell
agreely manual-consent create \
  --customer cust_8812 --document-version doc_v3 \
  --effective-date 2026-01-01 --valid-until 2031-01-01 \
  --item "Phone number:Billing" \
  --pdf ./signed-consent.pdf --json
# the hash alone is sent; add --upload to also escrow the raw bytes
curl -sS https://api.agreely.ca/v1/manual-consents \
  -H "Authorization: Bearer $AGREELY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cust_8812",
    "documentVersionId": "doc_v3",
    "effectiveDate": "2026-01-01",
    "validUntil": "2031-01-01",
    "items": [{"category":"Phone number","purpose":"Billing"}],
    "evidence": {"pdfSha256":"0x…"}
  }'

La réponse porte consentId, merkleRoot, un consentRefs (un 0x-hex par cellule), assurance: "company_attested" et anchored: false (l'ancrage se produit ensuite, de façon asynchrone). Agreely.hashPdf est statique et n'appelle aucun réseau; elle produit exactement la forme attendue par evidence.pdfSha256.

Quelques règles à connaître :

  • items nomme les demandes cochées « Oui ». Il peut être vide si chaque demande a reçu un « Non ». Les lignes que le document donne à titre d'information sont ajoutées par le serveur comme reconnues, jamais comme des consentements; la réponse les liste dans acknowledged.
  • effectiveDate est la date de la signature, jamais dans le futur.
  • Une finalité sensible fondée sur le consentement exige "sensitiveExpressAttested": true : l'organisation atteste que le consentement a été donné expressément. Agreely consigne cette attestation, il ne la vérifie pas.
  • Une feuille signée avant la publication de la version choisie exige "versionAttested": true : l'organisation atteste que la feuille demandait le consentement pour les mêmes finalités, avec la même information.
  • Passez un en-tête Idempotency-Key : une nouvelle tentative avec le même corps rejoue la première réponse et ne consigne rien de neuf.
  • Chaque refus porte une reason stable (predates_withdrawal, relationship_ended, sensitive_express_required, ...). Comparez-la, jamais le message. La liste complète est dans la référence de l'API, à la section « Consigner un consentement sur papier ».

Il s'applique à l'identique

Un consentement attesté par l'entreprise et un consentement signé par le citoyen autorisent de façon identique à /v1/check. Seul le palier diffère : une vérification renverra assurance: "company_attested" et tier: "manual" au lieu de "citizen_signed" et "full". Le code qui protège une fonctionnalité n'a rien à changer.

Lier plus tard le consentement au citoyen

La personne peut, plus tard, rattacher ce consentement hors ligne à son propre identifiant décentralisé grâce à un lien de réclamation à usage unique. La feuille de signature en émet déjà un; pour un consentement consigné sans feuille produite par l'API, émettez-le à part :

const link = await agreely.manualConsents.createClaimLink({
  customerId: "cust_8812",
  reference: "order-4471", // optional
});
// { claimUrl, token, expiresAt } - single-use

À la CLI : agreely manual-consent claim-link --customer cust_8812 --reference order-4471.

Par téléphone

Il vous faut une clé à portée attest_verbal.

Le script à lire

Le script à lire à la personne se trouve dans l'application Web d'Agreely : dans la fiche du client, à la page Consentement verbal, choisissez le document puis affichez le script. Il reprend l'information de la version, chaque demande une à une, et la relecture des réponses.

Par l'API, il n'y a pas de script à télécharger. Deux champs relient l'appel à ce qui a été lu :

  • documentVersionId lie le consentement à la version exacte du document lue au téléphone;
  • scriptVersion est le libellé que votre organisation donne au script qu'elle a lu (par exemple accueil-v3). Agreely le consigne tel quel dans le reçu.

Consigner le consentement verbal

Chaque demande posée reçoit une réponse explicite, "yes" ou "no" : il n'existe aucun raccourci qui consignerait une liste de finalités comme acceptées.

curl -sS https://api.agreely.ca/v1/verbal-consents \
  -H "Authorization: Bearer $AGREELY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: appel-client-7-2026-10-08" \
  -d '{
    "customerId": "client-7",
    "documentVersionId": "e4d41dc3-c8a5-44b1-96c5-be740c45cc6d",
    "answers": [
      {"category": "Photo", "purpose": "Publication", "answer": "yes"},
      {"category": "Adresse", "purpose": "Livraison de repas", "answer": "no"}
    ],
    "obtainedAt": "2026-10-08T14:05:00-04:00",
    "obtainedBy": "Luc Gagnon",
    "scriptVersion": "accueil-v3",
    "respondent": {"consentedBy": "self"},
    "validUntil": "2027-10-31",
    "paperExpected": true
  }'
# { "consentId": "...", "tier": "verbal", "assurance": "company_documented", "consentRefs": ["0x..."], ... }

obtainedAt est l'instant de l'appel, la date du consentement : au plus 7 jours dans le passé et jamais dans le futur, pas même d'une seconde (obtained_at_in_future). Un consentement plus fort déjà en vigueur pour une finalité, sur papier ou par clé d'accès, n'est jamais remplacé par un appel (stronger_consent_active), sauf dans la fenêtre de renouvellement décrite plus bas. Pour une personne mineure de moins de 14 ans, le répondant doit être le titulaire de l'autorité parentale ou le tuteur.

Recevoir la feuille signée qui confirme l'appel

Avec paperExpected: true, l'organisation envoie à la personne une feuille qui reprend les demandes. Quand elle revient signée, consignez-la avec une clé à portée attest :

curl -sS https://api.agreely.ca/v1/verbal-consents/$CONSENT_ID/paper \
  -H "Authorization: Bearer $AGREELY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signedAt": "2026-10-20T10:30:00-04:00",
    "answers": [{"category": "Photo", "purpose": "Publication", "answer": "yes"}],
    "evidence": {"pdfSha256": "0x..."}
  }'

Le consentement verbal n'est jamais réécrit : chaque finalité cochée passe dans un nouveau consentement manual, que la vérification suit dès lors. Le consentement date toujours de l'appel; la signature est sa date de preuve. Une case laissée sans « Oui » sur la feuille est consignée comme un retrait daté de la signature. Si la feuille ne revient jamais, le consentement reste verbal : Agreely ne le fait pas expirer pour autant. GET /v1/verbal-consents/{consentId} donne l'historique complet de l'appel et de la feuille.

Renouveler par téléphone une feuille qui arrive à échéance

Un consentement signé sur papier dont la fin tombe dans les 30 jours civils peut être renouvelé par téléphone. Ces 30 jours sont une règle de produit d'Agreely, pas un délai prévu par la loi. La requête est un POST /v1/verbal-consents ordinaire :

  • c'est un nouveau consentement; la feuille n'est jamais réécrite et reste consignée telle quelle;
  • /v1/check répond aussitôt tier: "verbal" avec le nouveau validUntil, puis manual quand la nouvelle feuille signée revient. Si votre système exige manual pour un usage, il verra verbal entre l'appel et le retour de la feuille;
  • le renouvellement ne peut pas prendre fin avant la feuille (renewal_ends_before_current) ni être daté avant sa signature (renewal_predates_current);
  • un « Non » au renouvellement ne retire rien : la feuille reste en vigueur jusqu'à sa propre fin.

Hors de la fenêtre, l'appel est refusé comme d'habitude. Un consentement signé par clé d'accès ne se renouvelle jamais par téléphone : renouvelez-le par une nouvelle demande en ligne.

Retirer un consentement hors ligne

Deux routes, selon ce que vous retirez :

  • POST /v1/manual-consents/{consentRef}/revoke (portée attest, ou attest_verbal pour un consentement verbal) retire un consentement que l'organisation a consigné. Sa réponse dit dans gate ce que /v1/check répond désormais pour la finalité.
  • POST /v1/customers/{customerRef}/consents/{consentRef}/withdrawal (portée withdraw) consigne le retrait demandé par la personne sur n'importe quel consentement, y compris celui qu'elle a signé en ligne avec sa clé d'accès. Cette route reste ouverte pendant un défaut de paiement.

Dans les deux cas, un retrait s'attache à la finalité : retirer par n'importe quelle référence de la chaîne (un renouvellement et la feuille qu'il renouvelle, un appel et la feuille qui l'a confirmé) retire le consentement en cours. Une feuille ou un appel daté avant un retrait consigné ne le rouvre jamais (predates_withdrawal).

La limite honnête

Un consentement consigné par l'organisation ne prouve pas qu'un humain a consenti

Un consentement company_attested documente que l'organisation a attesté détenir une feuille signée dont l'empreinte correspond à ce qui a été consigné. Il ne prouve pas qu'un humain a bel et bien signé, ni qui a signé : il n'y a pas d'assertion par clé d'accès de la personne concernée. Un consentement company_documented est plus faible encore : il consigne que l'organisation a déclaré, à l'instant consigné (l'empreinte du reçu est ensuite ancrée), que la personne a consenti par téléphone à ces finalités sous ce script; il ne prouve pas que l'appel a eu lieu. Ce sont des voies légitimes pour les cas sans clé d'accès, et c'est pourquoi assurance et tier les nomment explicitement partout.

Ensuite

  • Référence de l'API : chaque route, ses corps, ses réponses et ses raisons de refus.
  • Demandes de consentement : la voie signée par le citoyen, et le contexte côté entreprise du consentement hors ligne.
  • Portail citoyen : ce que voit la personne concernée lorsqu'elle réclame et confirme son consentement.
  • Vérifier un reçu : un reçu company_attested se vérifie entièrement hors ligne.