Skip to main content
A mandate authorizes the exchange to debit an investor’s bank account up to a ceiling amount. Once registered and active, it can fund purchase payments without the investor approving each debit.

Endpoint

Response 201:
auth_link is a confirmation URL you can redirect the investor to for approving an ENACH mandate — the same link the exchange already emails/SMSes them. It’s fetched best-effort at creation time and is absent (field omitted) for a PHYSICAL mandate, or if it isn’t ready yet. GET /api/mandates/v1/:id retries fetching it while it’s missing, so poll that endpoint if you need it and it wasn’t in the create response.

Fields

Validation

Rejected synchronously with 400 VALIDATION_FAILED:
  • start_date unparseable or in the past.
  • end_date unparseable or not after start_date.
  • type not ENACH or PHYSICAL.
  • amount not greater than 0.
  • Neither bank_account_id nor the full inline trio (account_no + ifsc + account_type) supplied.
  • investor_id doesn’t exist.

Status lifecycle

Observed status values: PENDING, REGISTERED, REJECTED, CANCELLED. GET /api/mandates/v1/:id refreshes the status live from the exchange before returning it, so polling this endpoint reflects the latest registration state. Or listen for webhook events mandate.registered, mandate.rejected, mandate.cancelled instead of polling.

Upload a physical mandate scan

Form field file — the scanned, signed mandate form. Only valid for a PHYSICAL mandate. On acceptance the mandate becomes REGISTERED; a rejection returns 422 UCC_REJECTED.
Associates a bank-assigned Unique Mandate Reference Number with the mandate.

Using a mandate for payment

When a payment references a mandate, two checks run at payment time:

Read endpoints

Instead of registering a mandate directly, you can propose one and have the investor confirm it themselves — the same self-serve pattern as the public onboarding link for investors and the public order link.
Response 201: { "success": true, "data": { "link_id": "8f3e2b1a-..." } } — no mandate is registered yet, only the proposal. Share https://<your-ui>/mandate-confirm?linkId=8f3e2b1a-... with the investor. The investor reviews it via GET /api/public/v1/mandate-links/:link_id (X-Draft-Secret header for the PIN, if set) and confirms via POST /api/public/v1/mandate-links/:link_id/confirm — the same validated create path as POST /api/mandates/v1/, returning the same response shape including auth_link. Both the pre-confirm and post-confirm GET response also include a bank_display object — { "account_no": "****1234", "ifsc": "...", "account_type": "..." } — a masked view of the proposal’s bank account, resolved server-side. The public link never returns a raw bank_account_id or account number, whether the proposal referenced a saved bank account or was built from a manually-typed account_no/ifsc. auth_link (ENACH only) is where the investor should be redirected to approve the debit with their bank — the same link the exchange already emails/SMSes them. It’s a best-effort fetch and can lag a beat behind confirmation, so don’t assume it’s present the instant confirm returns: poll GET /api/public/v1/mandate-links/:link_id every few seconds until mandate.auth_link appears (it’s blank for PHYSICAL mandates and stays blank if the mandate was REJECTED), then redirect. As with order links, this link expires after 7 days (410 GONE) and a second confirm on the same link is 409 ALREADY_CONFIRMED — unlike the investor onboarding link, which never expires.

Next step

Create a purchase order and pay for it with this mandate.