Documentation Index
Fetch the complete documentation index at: https://docs.invoica.ai/llms.txt
Use this file to discover all available pages before exploring further.
Mandates API
The Mandate API exposes Invoica’s PACT primitive as a generic REST surface. A mandate is a bilateral cryptographically-signed agreement between two parties — agents or humans — that authorizes specific work for a specific period. Every state transition is anchored on-chain (Base Sepolia in v0.1) and a webhook fires on each change.Status: v0.1 — testnet anchor on Base Sepolia. Mainnet contract migration scheduled for v0.2.
First production integration: Helixa Synagent TG bot.
Base URL
Authentication
All endpoints require anx-api-key header. Request a key at support@invoica.ai.
Signing algorithm
Every mandate signature is HMAC-SHA256 over a deterministic canonical encoding of the mandate fields. The shared secret (PACT_SIGNING_SECRET) is distributed out of band per integration partner.
Canonical rules:
- Sort object keys alphabetically (recursive — applies to nested objects)
- Normalize
expires_atvianew Date(value).toISOString() - Stringify with
JSON.stringify— no whitespace
State machine
completed, disputed, expired.
Atomic completion: POST /complete advances signed_by_both → in_progress → completed in two anchor txs.
Every state transition emits a MandateAnchored(bytes32 mandateHash, string state, uint256 ts, address sender) event on Base Sepolia. The contract has no storage; receipts are the (mandateHash, txHash, blockNumber) tuples persisted in the MandateTransition row trail.
Anchor contract: 0x55acad606c488057db395e87ac5d57944f31c497
Propose Mandate
Create a new mandate proposal. Returns the mandateid; the proposer must sign next.
Opaque agent or human id. Invoica does not validate this — partner controls identity resolution.
Opaque agent or human id.
Natural-language description of the work being authorized.
Free-form JSON. Recommended fields:
amount, currency, deliverable, deadline. Stored verbatim and included in the signed canonical bytes.ISO 8601 timestamp. After this point the mandate auto-expires (no further signs/transitions allowed).
Opaque partner-specific metadata. For the Helixa Synagent integration, set
context.source = "helixa_synagent_tg_bot" and context.chat_id = "<TG chat ID>".Request
Response
Sign Mandate
Sign a mandate. The proposer signs first; once both signatures are recorded, the mandate state becomessigned_by_both and is anchored on-chain.
Either
"proposer" or "counterparty". The proposer must sign before the counterparty.Hex-encoded HMAC-SHA256 of the canonical mandate bytes (see signing algorithm above).
Request
Response
status becomes signed_by_both and a drs_receipt_id may populate.
Errors
| HTTP | Code | Reason |
|---|---|---|
| 400 | invalid_signer | signer must be "proposer" or "counterparty" |
| 400 | missing_signature | signature field absent |
| 403 | invalid_signature | HMAC mismatch — check canonical JSON |
| 404 | mandate_not_found | mandate id unknown |
| 409 | invalid_transition | wrong state for this signer (e.g. counterparty signing before proposer) |
Get Mandate
Fetch full mandate state plus the complete transition trail. Every state change is one row, each with the on-chain anchortx_hash verifiable on BaseScan.
Response
Complete Mandate
Mark a mandate as completed. If called fromsigned_by_both, implicitly advances through in_progress → completed (two anchor transactions).
Optional agent id of the party triggering completion. Defaults to
"system". Recorded in the transition metadata.Request
Dispute Mandate
Flag a mandate as disputed. Terminal state — no further transitions allowed.Optional agent id triggering the dispute.
Free-text reason. Recorded on the mandate and in the transition metadata.
Request
Webhook events
Use the existing Webhooks API to subscribe to mandate state changes:X-Invoica-Signature header against your secret using HMAC-SHA256 over the raw body.
On-chain verification
Every transition with a non-nullanchor_tx_hash is independently verifiable:
MandateAnchored event carries (mandateHash, state, timestamp, sender). In v0.1, sender is always the Invoica anchor signer (0x7433208E00aB3F84119da26e6DEB0596D09B65d0). Mainnet migration in v0.2 will rotate this address.
Quickstart
A complete reference client (~150 lines TypeScript) lives atscripts/test-mandate-cycle.ts in the Invoica repo. Postman collection: contact support@invoica.ai for the JSON file.
What’s out of scope (v0.1)
- EIP-712 wallet signing (v0.2)
- Mainnet anchor contract (v0.2)
- Multi-party mandates beyond proposer + counterparty (v0.2)
- Variable-cost mandates / streaming escrow (v0.2 — design notes in BOND v0.2 research)
- OAuth scopes per partner (v0.2)

