Skip to main content

Troubleshooting: CONSENT_RECEIPT_INVALID (422)

The India DPDP Phase II Consent Manager surface verifies the signed consent receipts you persist or re-verify. When verification fails, the API rejects the request with a 422 and code CONSENT_RECEIPT_INVALID:
This page maps each symptom to the check that fired and the fix you can run yourself. For the concept behind receipts — registration, minting, and canonicalized signing — see Consent Management → Consent receipts.
Consent receipts are a tenant-owned compliance control: your Consent Manager issues and signs the receipt, and Orbit verifies it against the public key you registered. The opt-in / opt-out record that results lives in your consent ledger — Orbit enforces nothing beyond the verification itself.

Symptom map

Work through the symptom table in order — the two endpoints both surface exactly three failure shapes, and the message tells you which one fired. POST /api/v1/compliance/consent/receipts mints a receipt; POST /api/v1/compliance/consent/receipts/:id/verify re-checks a stored one. The registry lists CONSENT_RECEIPT_INVALID as varies for HTTP status because the mint endpoint rejects structurally-degenerate receipts at 422 VALIDATION_ERROR instead (a bad ISO-8601 timestamp, a malformed Base64URL signature, an empty payload, or a payload that disagrees with the displayed receipt fields). A structural problem gets the 422 VALIDATION_ERROR; a cryptographic failure once structure passes gets the CONSENT_RECEIPT_INVALID above. Only verified receipts are persisted — verification always runs before storage.

How receipts are issued, and when the API rejects the request

Two CONSENT_RECEIPT_INVALID paths exist:
  1. Mint (POST /compliance/consent/receipts) — persist a receipt your Consent Manager signed. The manager must be registered and active; the signature must verify before anything is stored (Orbit never persists a receipt it cannot verify).
  2. Re-verify (POST /compliance/consent/receipts/:id/verify) — re-check a stored receipt against the issuing manager’s current key (an audit step, or a check on a suspected key rotation). The {id} accepts either the consent-record id or the receipt_id.
The “unknown manager” check and the signature check differ between the two endpoints: at mint, a wrong consent_manager_id or a known-but-inactive manager fires the wrong-manager throw. At re-verify, a deleted manager row fires the no-longer-registered throw. In both cases the signature failure means the same thing: the payload changed after signing, or the key the platform holds is not the key that signed (say the manager rotated keys without notifying you).
  1. Register the manager under Settings → Compliance → Consent managers (or via POST /api/v1/compliance/consent/managers) with its machine manager_id, HTTPS URL, and SPKI PEM public key.
  2. Point the mint request’s consent_manager_id at that same manager_id value.
  3. To fix manager deactivation, use PUT /compliance/consent/managers/:id with is_active: true.
On a pre-provisioned tenant (the consent_managers table missing) mint is fail-closed with exactly this error — the read endpoints degrade to empty / 404, but writes refuse. Re-run the provisioning migration before minting receipts.

Fix workflow: signature verification failed

Work through these in order — each isolates one of the three distict causes:
  1. Key rotation. The Consent Manager rotated its signing key without telling you. Register the manager’s new public key under Settings → Compliance → Consent managers (or PUT /compliance/consent/managers/:id with the new public_key), and ask the manager to re-issue the receipt signed with the current key.
  2. Payload tampered in transit. The JSON you posted disagrees with what was signed — a copy-paste edit, a middleware transform, or the manager changed the payload after signing. Paste the receipt envelope exactly as the manager produced it.
  3. Canonicalization mismatch. Orbit canonicalizes the payload before hashing (sorted keys, insignificant-whitespace stripped — a minimal RFC 8785 JCS form, not a spec-complete implementation). If the manager signed a different serialization, ask it to sign the same sorted-key form Orbit uses.
Re-issue the receipt by posting the corrected envelope to POST /compliance/consent/receipts again. The upsert targets the same contact_id + channel pair, so a corrected re-issue replaces the failed attempt’s pending soft-fact with the verified one.

Fix workflow: manager no longer registered

If POST /receipts/:id/verify says the issuing Consent Manager is no longer registered, the receipt still exists but its trust anchor (consent_managers row) was deleted. Re-register the manager with the same manager_id — re-verification then re-checks against the new row’s key.

Still failing? Pass to support

Include in the ticket:
  • The request_id from meta.request_id on the 422 response
  • Whether the failure was mint or re-verify, and the consent_manager_id from error.details
  • The exact receipt envelope you posted (or the stored {id}), so support can replay the structure and signature checks without asking you to reproduce