Consumer Delegation
Agentic transaction governance: your customers authorize AI agents to transact on their behalf, and every transaction is governed by the delegation they granted. This page is the integration contract — the flows, configuration shapes, and refusal codes. It assumes the Quickstart. For governing your own trading agents (strategies and PM mandates), see Agentic Trading.
The integration loop
- Register the subject. Your CIAM asserts the customer; Eniyan mints a pairwise pseudonymous subject. No PII crosses the wire — you keep the mapping.
- Run the consent ceremony. Your app submits the session signals you attest; Eniyan scores them into a Consent Assurance Level (CAL). Signals of duress or coercion cap the score outright.
- Activate the delegation. The grant becomes a durable record: tier, scopes, per-transaction cap, windowed budget, counterparty allow-list, expiry — plus the vertical constraints below. One live delegation per customer–agent pair.
- Mint. The agent presents its credential, the delegation reference, and RFC 9396 authorization_details naming the exact transaction — and receives a 5-minute token (consumer as subject, agent as actor per RFC 8693).
- Verify and report. Introspect via RFC 7662 — the delegation is re-evaluated live at that moment. Report executed spend to the budget ledger.
- Step up — or revoke. When a step-up rule matches, the mint refuses with the artifacts your app needs to resolve it (below). Revocation flips the very next introspection to inactive.
Vertical packs
Scopes are organized into enableable packs on your configuration (enabled_verticals on PUT /v1/consumer/config): retail and banking are included; capital markets and healthcare each additionally require their add-on (/v1/billing/add-ons/capital-markets / /v1/billing/add-ons/healthcare) and fail closed if it lapses. Core read scopes are always available.
- An omitted enabled_verticals preserves your current selection; a config with no selection ever made means retail + banking.
- Disabling a pack is a live kill switch: new grants refuse, and existing delegations carrying its scopes go dark on the very next mint or introspection (vertical_disabled). Re-enabling resumes them — no reinstatement ceremony. Disabling only ever narrows.
- GET /v1/consumer/verticals is the machine-readable catalogue: every pack with its scope family, transaction types, enablement state, and suggested step-up rules.
Scope catalogue
| Scope | Tier | What the customer sees | Pack |
|---|---|---|---|
| consumer:account:read | read_only | See your account details | core |
| consumer:activity:read | read_only | See your activity history | core |
| consumer:profile:read | read_only | See your profile information | core |
| consumer:orders:propose | propose | Prepare orders for your approval | retail |
| consumer:orders:place | execute_capped | Place orders on your behalf | retail |
| consumer:returns:initiate | propose | Start returns for your approval | retail |
| consumer:subscriptions:manage | execute_capped | Manage your subscriptions | retail |
| consumer:payments:initiate | execute_capped | Start payments on your behalf | banking |
| consumer:counterparties:manage | execute_full | Manage who you can pay | banking |
| consumer:cards:control | execute_full | Control your card settings | banking |
| consumer:portfolio:read | read_only | See your investments and balances | capital_markets |
| consumer:trades:propose | propose | Prepare trades for your approval | capital_markets |
| consumer:trades:place | execute_capped | Place trades on your behalf, within your limits | capital_markets |
| consumer:trades:schedule | execute_capped | Run your scheduled, pre-authorized trades | capital_markets |
| consumer:prescriptions:read | read_only | See your prescriptions and refill status | healthcare |
| consumer:prescriptions:propose | propose | Prepare refill orders for your approval | healthcare |
| consumer:prescriptions:renewal_request | propose | Ask your prescriber to renew a prescription | healthcare |
| consumer:prescriptions:fill | execute_capped | Order and pay for refills of prescriptions you designate | healthcare |
| consumer:prescriptions:fill_controlled | execute_capped | Include the controlled-substance refills you designate | healthcare |
| consumer:prescriptions:schedule | execute_capped | Run your scheduled, pre-authorized refills | healthcare |
Two deliberate absences: there is no uncapped trading scope (capped execution is the product), and the only Schedule II prescription verb is renewal_request at propose tier — an agent can ask you to route a renewal to the prescriber, never execute one.
Step-up policy configuration
Your step-up policy is a versioned list of rules. Each rule matches on a scope or a delegation tier, optionally floored by an amount, and demands one or more methods:
- platform_approval / platform_approval_mfa — your in-app approval loop; the MFA variant requires an MFA-grade assertion with the decision.
- eniyan_mfa — an Eniyan-hosted passkey or TOTP challenge showing the exact transaction. Requires the customer to have verified identity and enrolled an authenticator.
- verify_document / verify_document_liveness / verify_document_liveness_id — a Stripe Identity check at rising assurance (document; + selfie; + ID number). Consumer consent is captured before any biometric step.
Verification freshness is per rule: a max-age window makes one check durable across transactions; a zero window demands a fresh check bound to each transaction's exact terms. When several rules match one mint, their requirements combine — rules are floors, never ceilings. Two additions with the vertical packs:
- Pack suggestions are advisory. The step-up GET returns a suggested block (source pack_default) for your enabled packs — rules you can adopt verbatim with a PUT. They are never enforced until you adopt them. Enable capital markets or healthcare alongside a policy review.
- Verticals can inject floors. Healthcare fills paid by Medicare Part D or Medicaid require a per-fill platform approval by default (org-overridable via the delegation's payer configuration) — injected requirements combine with your policy exactly like matching rules. Scheduled transactions never bypass step-up: pre-authorization is consent, not an exemption.
The full reference for this surface is delivered to customers under NDA.
Windows & schedules
Delegations can constrain when an agent may transact, and pre-authorize recurring transactions. Both live in the vertical constraint subtree the customer consents to at the ceremony (constraints.trading / constraints.healthcare), always in one declared IANA timezone:
- Windows (days + start/end times): a discretionary mint outside the window refuses with the next-open time. Evaluation happens in the declared timezone, so a "9:30–4:00" intent survives DST.
- Schedules (daily / weekly / monthly / every-N-days with an anchor date): each entry names the exact instrument-or-prescription, amount, and cadence. Schedule ids are server-assigned at activation — read them back from the delegation hub; they never appear on consumer-facing surfaces.
- Once per occurrence: a scheduled mint must match its schedule exactly and consumes that occurrence — replays refuse, and the notional holds against the budget in the same write. An occurrence is due for its whole calendar day, with optional grace past midnight.
Web execution
With the org opt-in on (PUT /v1/consumer/config web_execution_enabled, or Settings → Consumer Delegation → Web execution), the same delegations execute at ordinary web checkouts through the eniyan-web browser gate — identical caps, budgets, counterparty allow-lists, step-up, and ledger on either surface:
- Web counterparties: allow-list entries may be the merchant’s web domain — shop.example (exact) or *.shop.example (apex + every subdomain, dot-boundary). The gate mints with the page host it is actually on as merchantRef — never a model-asserted value — and the toggle activates the same domain-aware matching for API mints. Opaque refs keep exact matching; with the toggle off, domain-shaped entries are inert (fail closed).
- Step-up at the checkout: the mint’s 403 carries the approval reference (and the challenge link under Eniyan-hosted MFA); the agent relays it to the consumer through your platform and retries with approval_id. The consumer approves the exact store and amount; any drift burns the approval.
- Fill-less by design: the authorization gates the checkout submit — merchant-saved cards, wallet buttons, and payment methods on file ride it. Eniyan touches no payment instrument of any kind.
- Honest ledger: report execution to POST /v1/consumer/delegations/{ref}/usage with the mint’s reserve key as platform_txn_ref — the reserved hold flips to executed at the reported amount instead of double-counting (the response says reserved_flip). This flip benefits API integrations identically.
Healthcare pack
Agents fill and pay for prescriptions the customer designates — the allow-list is mandatory for fill authority, per prescription, always. Regulatory posture, encoded as contract:
- Eniyan never holds patient data. Prescription and pharmacy refs must be opaque single-token platform identifiers — free text and drug-code shapes (NDC) are refused at the schema layer, and every Eniyan-rendered surface truncates refs to their last 4 characters. Your platform keeps the mapping and the patient record. Reflect Eniyan as a service provider/processor in your privacy notices.
- Schedule II is never fillable by an agent (21 CFR 1306.12) — unconditional, regardless of scopes or consent. Controlled fills at schedules III–V require the separate controlled-fill scope AND the delegation's controlled consent, optionally capped by class.
- Payer rules: Medicare Part D and Medicaid default to per-fill human confirmation (your org can override the payer list per delegation). Early-refill spacing is enforced per designated prescription.
- Consumer refill requests are outside EPCS (21 CFR 1311) — prescription issuance stays prescriber-side. Your platform remains the covered entity/pharmacy of record: dispensing decisions, state pharmacy law, FSA/HSA eligibility handling, and coupon rules stay with you. Eniyan authorizes transactions, never dispensing. This documentation is not legal advice — engage your own counsel.
Consumer transparency view links
Mint a signed, Eniyan-hosted view link per delegation and deliver it to your customer — they see exactly what they authorized (labelled scopes, caps, remaining budget, trading limits, designated prescriptions as truncated refs, schedules in plain language) and the step-up rules protecting them, with no account. Hosted links are double-gated: your org must hold the view-links add-on and the agent must have passed Eniyan's transparency review. Links are revocable, expire on a TTL you control, and the page goes dark if the agent's review approval is withdrawn. The org-API delegation hub is not gated — render it in your own app at no extra cost.
Mint refusal codes
A refused consumer mint returns a standard OAuth error body; branch on the code:
| Code | When |
|---|---|
| amount_exceeds_cap | The transaction amount is over the delegation's per-transaction cap. |
| counterparty_not_allowed | The counterparty is not on the delegation's allow-list. |
| budget_exceeded | The windowed budget has no room for this amount. |
| rar_scope_mismatch | The authorization_details type is not permitted by the granted scopes (e.g. a trade order on a retail-only grant, or a discretionary trade on a schedule-only grant). |
| approval_required | A step-up rule demands the customer's approval; retry with approval_id after they decide. |
| verification_required | A step-up rule demands an identity check; the response carries a requirement reference. |
| enrollment_required | An Eniyan-hosted MFA rule matched but the customer has no enrolled authenticator. |
| step_up_required | Multiple step-up requirements are unmet; the response carries each reference. |
| delegation_not_live | The delegation is revoked, expired, suspended, its consent no longer supports the tier, or its vertical pack was disabled (vertical_disabled — the pack kill switch). |
Trading (capital-markets pack)
| Code | When |
|---|---|
| instrument_required / invalid_side / invalid_order_type | The trade entry is malformed: missing instrument, or a side/order type outside the vocabulary. |
| limit_price_required | A limit or stop-limit order arrived without a positive limit_price_minor. |
| instrument_not_allowed | The instrument is not on the delegation's allow-list. |
| side_not_allowed / order_type_not_allowed | The side or order type is outside what the customer consented to. |
| trade_count_exceeded | The delegation's max_trades_per_day is already consumed. |
| outside_trading_window | A discretionary trade outside the consented trading hours; the detail carries the next window-open time. |
| schedule_unknown / schedule_not_due | The schedule_id doesn't exist on this delegation, or has no due occurrence now. |
| schedule_amount_mismatch / schedule_instrument_mismatch / schedule_side_mismatch | A scheduled trade must present the exact pre-authorized amount, instrument, and side. |
| schedule_occurrence_consumed | This occurrence was already used — scheduled trades are once-per-occurrence. |
| schedule_scope_required | Scheduled trades require the scheduled-trading scope in the grant. |
Prescriptions (healthcare pack)
| Code | When |
|---|---|
| prescription_required / invalid_prescription_ref | The fill entry is missing a prescriptionRef, or the ref failed the opaque-identifier guard (free text and drug-code shapes are refused). |
| prescription_not_designated | The prescription is not on the delegation's designated list — designation is per-prescription, always. |
| schedule_ii_refill_prohibited | UNCONDITIONAL: Schedule II prescriptions cannot be refilled by an agent under any consent combination (21 CFR 1306.12). Route a renewal request to the prescriber instead. |
| controlled_not_allowed | A controlled-substance fill without BOTH the controlled-fill scope and the delegation's controlled consent. |
| schedule_class_exceeds_max | The fill's schedule class is more restricted than the delegation permits. |
| refill_too_early | This prescription filled within the delegation's minimum spacing window. |
| outside_fill_window | A discretionary fill outside the consented fill windows. |
| invalid_payer_type / invalid_schedule_class / invalid_day_supply | The entry carries a payer, schedule class, or day supply outside the vocabulary. |
General API errors are on Errors & rate limits.
CAL scoring model
CAL weighs evidence across four classes — presence, freedom, session integrity, and comprehension — with hard caps for duress and coercion signals, and each delegation tier demands a minimum score. The at-grant score is immutable; the current score reprices as late signals arrive.
The full reference for this surface is delivered to customers under NDA.