Download OpenAPI specification:Download
Issuing, settlement, refunds, and on-ramp infrastructure for partner platforms.
Creates a virtual card for the given cardholder. Behavior depends on the ISSUING_PROVIDER config: Stripe issues a Stripe Issuing card; Bridge creates a Bridge card account funded by the supplied crypto account.
| cardholderId required | string Cardholder UUID returned from POST /v1/cardholders. |
| chain | string Enum: "solana" "world_chain" "base" Bridge only — blockchain for the card account funding source. |
| cryptoAccountAddress | string Bridge only — crypto account address that funds card draws. |
| cryptoAccountType | string Enum: "standard" "bridge_wallet" Bridge only — crypto account type. Defaults to |
{- "cardholderId": "550e8400-e29b-41d4-a716-446655440000",
- "chain": "solana",
- "cryptoAccountAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
- "cryptoAccountType": "standard"
}{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "stripeCardId": "ic_1NXxxx",
- "bridgeCardAccountId": "card_acc_abc123",
- "last4": "4242"
}Returns a Stripe Issuing ephemeral key suitable for Apple Pay In-App Provisioning, Google Pay JS push tokenization, or client-side Stripe.js PAN display. Stripe-only: rejects with 400 when ISSUING_PROVIDER=bridge. Tightly rate-limited (5/min/IP) because ephemeral keys are sensitive.
| id required | string Example: 6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1 Permara card UUID |
| platform required | string Enum: "apple" "google" Target wallet vendor. |
| nonce | string Required for Apple/Google Pay In-App Provisioning push tokenization. Omit for client-side card display via Stripe.js (PAN reveal). |
| nonceSignature | string Apple Pay only — base64 signature over |
| certificates | Array of strings Apple Pay only — array of base64 certificates from PKAddPaymentPassRequest. Required when |
{- "platform": "apple",
- "nonce": "string",
- "nonceSignature": "string",
- "certificates": [
- "string"
]
}{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "stripeCardId": "ic_1NXxxx",
- "platform": "apple",
- "ephemeralKey": {
- "id": "ephkey_1NX...",
- "secret": "ek_test_...",
- "expires": 1715000000,
- "associated_objects": [
- {
- "id": "string",
- "type": "string"
}
]
}
}The configured per-transaction / daily / weekly / monthly caps and MCC rules for a card.
| id required | string Permara card UUID |
{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "perTransactionUsd": "250.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00",
- "blockedMcc": [ ],
- "allowedMcc": null
}Sets per-transaction / daily / weekly / monthly USD caps and MCC block/allow rules. Only the fields sent are changed; an explicit null clears a cap or the allowlist. Enforced in real time on every authorization for the card.
| id required | string Permara card UUID |
| perTransactionUsd | object or null Per-transaction USD cap. |
| dailyUsd | object or null Rolling 24h USD cap. |
| weeklyUsd | object or null Rolling ISO-week USD cap. |
| monthlyUsd | object or null Calendar-month USD cap. |
| blockedMcc | Array of strings MCCs to decline. Replaces the existing list. |
| allowedMcc | Array of strings or null When set, only these MCCs are allowed. |
{- "perTransactionUsd": "250.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00",
- "blockedMcc": [
- "7995"
], - "allowedMcc": [
- "5411",
- "5812"
]
}{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "perTransactionUsd": "250.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00",
- "blockedMcc": [ ],
- "allowedMcc": null
}Sets the card inactive at Stripe and in Permara — subsequent authorizations decline immediately.
| id required | string Permara card UUID |
{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "status": "inactive",
- "last4": "4242",
- "safeAddress": "0x1111111111111111111111111111111111111111"
}Reactivates a frozen card.
| id required | string Permara card UUID |
{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "status": "inactive",
- "last4": "4242",
- "safeAddress": "0x1111111111111111111111111111111111111111"
}Issues a Safe-funded card drawing USDC from the wallet’s Safe, seeding its spend limits from the body. Sandbox-only (a Stripe cardholder is minted for the tenant on first use); live issuance requires KYB onboarding.
| walletId required | string Source wallet id (must be DEPLOYED). |
| perTransactionUsd | object or null Per-transaction USD cap. |
| dailyUsd | object or null Rolling 24h USD cap. |
| weeklyUsd | object or null Rolling ISO-week USD cap. |
| monthlyUsd | object or null Calendar-month USD cap. |
| blockedMcc | Array of strings MCCs to decline. Replaces the existing list. |
| allowedMcc | Array of strings or null When set, only these MCCs are allowed. |
| agentId | string Bind the card to an agent (its spend also accumulates under the agent). |
{- "perTransactionUsd": "250.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00",
- "blockedMcc": [
- "7995"
], - "allowedMcc": [
- "5411",
- "5812"
], - "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890"
}{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "stripeCardId": "ic_1NXxxx",
- "last4": "4242",
- "safeAddress": "0x1111111111111111111111111111111111111111",
- "status": "active"
}| phone | string Recipient phone (E.164). Exactly one of phone | did. |
| did | string Recipient DID (did:safebank / did:web form or bare handle). |
| amountUsd required | string USD amount (≤6 fraction digits). |
| chainId | number Source chain id (default 84532). |
| fundingMode | string Enum: "INTERNAL_BALANCE" "ONCHAIN_DEPOSIT" "SAFE_PROPOSAL" How the sender funds the payment. INTERNAL_BALANCE and ONCHAIN_DEPOSIT are available; SAFE_PROPOSAL ships later. |
| refundAddress | string ONCHAIN_DEPOSIT (EVM) only: address an expired/canceled escrow claim refunds to. Required for that mode. |
object Funding asset/network; {asset:'USDT',network:'tron'} rides the partner path. | |
object The payer-signed Universal Payment Envelope (DID payments). | |
| memo | string Plaintext memo — request metadata, never signed; the envelope binds only its memoHash. Stored under retention policy. |
| requestedDestinationId | string One of the RECIPIENT's active destination ids (server-verified ownership). |
| speedPreference | string Enum: "FASTEST" "CHEAPEST" |
| maximumFeeMinor | string Fee ceiling in destination-currency minor units. Routes whose total fees exceed it are excluded with MAX_FEE_EXCEEDED, never silently offered. |
| allowedRails | Array of strings Rail allowlist by destination type (e.g. PAYPAL, VENMO, SAFEBANK_BALANCE). Absent = all rails. |
object Invite a beneficiary who is not on Permara yet (email or mobile number — at least one). Valid only with DID addressing of a reserved/unknown handle, and required there: Permara reserves the handle, emails or texts an onboarding link, and the payment parks as a pending claim until they verify and choose a payout. |
{- "phone": "+15551234567",
- "did": "did:safebank:lance",
- "amountUsd": "25.00",
- "chainId": 0,
- "fundingMode": "INTERNAL_BALANCE",
- "refundAddress": "string",
- "funding": {
- "asset": "USDC",
- "network": "tron"
}, - "envelope": {
- "message": {
- "paymentObjectId": "string",
- "payer": "string",
- "payeeDid": "did:web:id.safebank.ai:lance",
- "amountBaseUnits": "string",
- "asset": "USD",
- "assetExponent": 0,
- "nonce": "string",
- "expiresAt": "string"
}, - "doc": {
- "policySha256": "string",
- "permittedSettlementAssets": [
- "string"
], - "permittedNetworks": [
- "string"
], - "permittedProviders": [
- "string"
], - "railExclusions": [
- "string"
], - "substitutionPermissions": {
- "destination": true,
- "provider": true,
- "rail": true,
- "network": true,
- "settlementAsset": true
}, - "allowRouteChange": true,
- "maxFeeBaseUnits": "string",
- "minRecipientProceeds": {
- "amountBaseUnits": "string",
- "asset": "EUR",
- "exponent": 0
}, - "maxAttempts": 0,
- "jurisdictionConstraints": [
- "string"
], - "memoHash": "string"
}, - "signature": "string"
}, - "memo": "string",
- "requestedDestinationId": "string",
- "speedPreference": "FASTEST",
- "maximumFeeMinor": "300",
- "allowedRails": [
- "string"
], - "invite": {
- "email": "finance@recipient.example",
- "phone": "+15551234567"
}
}{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}, - "quotes": [
- {
- "routeId": "string",
- "paymentId": "string",
- "destinationId": "string",
- "provider": "string",
- "sourceAmountBaseUnits": "string",
- "sourceAssetId": "string",
- "destinationAmountMinor": "string",
- "destinationCurrency": "string",
- "fees": { },
- "exchangeRate": "string",
- "estimatedDeliverySeconds": { },
- "speedClass": "INSTANT_EXPECTED",
- "guaranteeLevel": "CONTRACTUAL_SLA",
- "rank": { },
- "requiresBridge": true,
- "requiresConversion": true,
- "requiresPrefunding": true,
- "status": "string",
- "quoteExpiresAt": "string"
}
]
}{- "payments": [
- {
- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}
}
]
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}
}| id required | string |
{- "routes": [
- {
- "routeId": "string",
- "paymentId": "string",
- "destinationId": "string",
- "provider": "string",
- "sourceAmountBaseUnits": "string",
- "sourceAssetId": "string",
- "destinationAmountMinor": "string",
- "destinationCurrency": "string",
- "fees": { },
- "exchangeRate": "string",
- "estimatedDeliverySeconds": { },
- "speedClass": "INSTANT_EXPECTED",
- "guaranteeLevel": "CONTRACTUAL_SLA",
- "rank": { },
- "requiresBridge": true,
- "requiresConversion": true,
- "requiresPrefunding": true,
- "status": "string",
- "quoteExpiresAt": "string"
}
], - "excludedRoutes": [
- {
- "destinationId": "string",
- "provider": "string",
- "rail": "string",
- "reasonCode": "string"
}
]
}| id required | string |
| routeQuoteId required | string Route quote id to select. |
{- "routeQuoteId": "string"
}{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}
}| id required | string |
| amountMinor required | string Deposit amount in integer minor units. |
{- "amountMinor": "8000000"
}{- "paymentId": "string",
- "status": "CREATED",
- "recipientPhoneMasked": { },
- "recipientDid": "string",
- "envelopeId": "string",
- "recipientTenantId": { },
- "claimId": { },
- "sourceChainKey": "string",
- "sourceAssetId": "string",
- "sourceAmountBaseUnits": "string",
- "sourceFundingMode": "string",
- "requestedDestinationId": { },
- "selectedRouteQuoteId": { },
- "holdReasons": [
- "string"
], - "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string",
- "fundingInstructions": {
- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}, - "quotes": [
- {
- "routeId": "string",
- "paymentId": "string",
- "destinationId": "string",
- "provider": "string",
- "sourceAmountBaseUnits": "string",
- "sourceAssetId": "string",
- "destinationAmountMinor": "string",
- "destinationCurrency": "string",
- "fees": { },
- "exchangeRate": "string",
- "estimatedDeliverySeconds": { },
- "speedClass": "INSTANT_EXPECTED",
- "guaranteeLevel": "CONTRACTUAL_SLA",
- "rank": { },
- "requiresBridge": true,
- "requiresConversion": true,
- "requiresPrefunding": true,
- "status": "string",
- "quoteExpiresAt": "string"
}
]
}{- "approvals": [
- {
- "id": "string",
- "paymentId": "string",
- "requiredWeight": 0,
- "approvalGroup": { },
- "status": "PENDING",
- "receivedWeight": 0,
- "signatures": [
- {
- "memberId": "string",
- "decision": "APPROVE",
- "weightAtSigning": 0,
- "invalidatedAt": { },
- "createdAt": "string"
}
], - "createdAt": "string"
}
]
}| id required | string |
| decision | string Default: "APPROVE" Enum: "APPROVE" "REJECT" |
| signature | string EIP-191 signature over the approval vote message (optional hardening). |
{- "decision": "APPROVE",
- "signature": "string"
}{- "id": "string",
- "paymentId": "string",
- "requiredWeight": 0,
- "approvalGroup": { },
- "status": "PENDING",
- "receivedWeight": 0,
- "signatures": [
- {
- "memberId": "string",
- "decision": "APPROVE",
- "weightAtSigning": 0,
- "invalidatedAt": { },
- "createdAt": "string"
}
], - "createdAt": "string"
}| id required | string |
{- "id": "string",
- "paymentId": "string",
- "requiredWeight": 0,
- "approvalGroup": { },
- "status": "PENDING",
- "receivedWeight": 0,
- "signatures": [
- {
- "memberId": "string",
- "decision": "APPROVE",
- "weightAtSigning": 0,
- "invalidatedAt": { },
- "createdAt": "string"
}
], - "createdAt": "string"
}Normalized intents describe the payment (recipient/amount/funding/delivery) and let Permara route it. Legacy bodies (sourceWalletId + destination) continue to work with deprecation headers.
| x-safebank-2fa-challenge | string |
| idempotency-key required | string |
| Idempotency-Key | string |
required | object (UnifiedRecipientBody) |
required | object (UnifiedAmountBody) |
object (UnifiedFundingBody) | |
object (UnifiedDeliveryBody) | |
object (UnifiedPurposeBody) | |
object The payer-signed Universal Payment Envelope. Valid only with a DID recipient — same semantics as the off-ramp path. | |
| memo | string Plaintext memo — request metadata, never signed; the envelope binds only its memoHash. Stored under retention policy. |
| metadata | object Echoed back verbatim; never interpreted. |
| idempotencyKey | string Tenant-scoped replay key (or Idempotency-Key header). |
| requestedDestinationId | string One of the recipient's active destination ids (server-verified ownership). |
{- "recipient": {
- "phoneNumber": "+12125550123",
- "handle": "@acme-ops",
- "email": "string",
- "identityId": "string",
- "did": "did:safebank:lance",
- "walletAddress": "string"
}, - "amount": {
- "value": "250.00",
- "currency": "USD"
}, - "funding": {
- "asset": "USDC",
- "chain": "base",
- "chainId": 0,
- "network": "tron",
- "mode": "INTERNAL_BALANCE",
- "refundAddress": "string"
}, - "delivery": {
- "preference": "instant",
- "maximumFeeMinor": "string",
- "allowedRails": [
- "string"
]
}, - "purpose": {
- "type": "invoice",
- "invoiceId": "string",
- "memo": "string"
}, - "envelope": {
- "message": {
- "paymentObjectId": "string",
- "payer": "string",
- "payeeDid": "did:web:id.safebank.ai:lance",
- "amountBaseUnits": "string",
- "asset": "USD",
- "assetExponent": 0,
- "nonce": "string",
- "expiresAt": "string"
}, - "doc": {
- "policySha256": "string",
- "permittedSettlementAssets": [
- "string"
], - "permittedNetworks": [
- "string"
], - "permittedProviders": [
- "string"
], - "railExclusions": [
- "string"
], - "substitutionPermissions": {
- "destination": true,
- "provider": true,
- "rail": true,
- "network": true,
- "settlementAsset": true
}, - "allowRouteChange": true,
- "maxFeeBaseUnits": "string",
- "minRecipientProceeds": {
- "amountBaseUnits": "string",
- "asset": "EUR",
- "exponent": 0
}, - "maxAttempts": 0,
- "jurisdictionConstraints": [
- "string"
], - "memoHash": "string"
}, - "signature": "string"
}, - "memo": "string",
- "metadata": { },
- "idempotencyKey": "string",
- "requestedDestinationId": "string"
}{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| kind | string Enum: "legacy" "unified" |
| skip | string |
| take | string |
{- "payments": [
- {
- "id": "string",
- "sourceWalletId": "string",
- "destinationType": "handle",
- "destinationHandle": { },
- "destinationAddress": "string",
- "destinationChainId": 0,
- "asset": "usdc",
- "amount": "25.00",
- "status": "CREATED",
- "safeTxHash": { },
- "executedTxHash": { },
- "memo": { },
- "failureReason": { },
- "createdAt": "string"
}
], - "total": 0,
- "skip": 0,
- "take": 0
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| id required | string |
{- "routes": [
- {
- "routeId": "string",
- "paymentId": "string",
- "destinationId": "string",
- "provider": "string",
- "sourceAmountBaseUnits": "string",
- "sourceAssetId": "string",
- "destinationAmountMinor": "string",
- "destinationCurrency": "string",
- "fees": { },
- "exchangeRate": "string",
- "estimatedDeliverySeconds": { },
- "speedClass": "INSTANT_EXPECTED",
- "guaranteeLevel": "CONTRACTUAL_SLA",
- "rank": { },
- "requiresBridge": true,
- "requiresConversion": true,
- "requiresPrefunding": true,
- "status": "string",
- "quoteExpiresAt": "string"
}
], - "excludedRoutes": [
- {
- "destinationId": "string",
- "provider": "string",
- "rail": "string",
- "reasonCode": "string"
}
]
}| id required | string |
| routeQuoteId required | string Route quote id to select. |
{- "routeQuoteId": "string"
}{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| id required | string |
{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| id required | string |
| ownerAddress | string Owner address to act as. Optional for single-owner wallets. |
{- "ownerAddress": "string"
}{- "paymentId": "string",
- "status": "CREATED",
- "internalStatus": "string",
- "recipientKind": "string",
- "recipientDisplay": { },
- "envelopeId": { },
- "recipientIdentityId": { },
- "amountValue": "string",
- "amountCurrency": "string",
- "fundingAssetId": "string",
- "fundingChainKey": "string",
- "holdReasons": [
- "string"
], - "approvalRequestId": { },
- "selectedRouteQuoteId": { },
- "purpose": { },
- "metadata": { },
- "failureReason": { },
- "deliveredAt": { },
- "createdAt": "string"
}| id required | string |
| signature required | string Raw secp256k1 signature over the safeTxHash. |
{- "signature": "string"
}{- "id": "string",
- "sourceWalletId": "string",
- "destinationType": "handle",
- "destinationHandle": { },
- "destinationAddress": "string",
- "destinationChainId": 0,
- "asset": "usdc",
- "amount": "25.00",
- "status": "CREATED",
- "safeTxHash": { },
- "executedTxHash": { },
- "memo": { },
- "failureReason": { },
- "createdAt": "string"
}| id required | string |
| ownerAddress | string Owner address to act as. Optional for single-owner wallets. |
{- "ownerAddress": "string"
}{- "id": "string",
- "sourceWalletId": "string",
- "destinationType": "handle",
- "destinationHandle": { },
- "destinationAddress": "string",
- "destinationChainId": 0,
- "asset": "usdc",
- "amount": "25.00",
- "status": "CREATED",
- "safeTxHash": { },
- "executedTxHash": { },
- "memo": { },
- "failureReason": { },
- "createdAt": "string"
}What it costs for a payee (DID or handle) to receive an amount, given your funding asset. Exact-output by default: the recipient amount is guaranteed, the sender amount is solved. Quoting moves no funds and expires per the returned expiresAt.
{ }{- "quoteId": "string",
- "payee": {
- "did": "string",
- "verified": true
}, - "recipientSettlement": {
- "currency": "string",
- "railType": "string"
}, - "sender": {
- "requiredAmount": {
- "value": "string",
- "asset": "string",
- "chain": "string"
}, - "maxCostUsd": "string"
}, - "recipient": {
- "guaranteedAmount": {
- "value": "string",
- "currency": "string"
}
}, - "fees": {
- "total": {
- "value": "string",
- "currency": "string"
}, - "safebank": {
- "value": "string",
- "currency": "string"
}
}, - "estimatedSettlementSeconds": 0,
- "expiresAt": "string"
}| url required | string |
| enabledEvents required | Array of strings |
| description | string |
{- "enabledEvents": [
- "payment.*"
], - "description": "string"
}{- "id": "string",
- "url": "string",
- "enabledEvents": [
- "string"
], - "status": "string",
- "description": { },
- "createdAt": "string",
- "secret": "string"
}| id required | string |
| status | string Enum: "ACTIVE" "DISABLED" |
| enabledEvents | Array of strings |
{- "status": "ACTIVE",
- "enabledEvents": [
- "string"
]
}{- "id": "string",
- "url": "string",
- "enabledEvents": [
- "string"
], - "status": "string",
- "description": { },
- "createdAt": "string"
}| id required | string |
{- "id": "string",
- "url": "string",
- "enabledEvents": [
- "string"
], - "status": "string",
- "description": { },
- "createdAt": "string",
- "secret": "string"
}| endpoint_id | string |
{- "deliveries": [
- {
- "id": "string",
- "eventId": "string",
- "endpointId": "string",
- "status": "string",
- "attempts": 0,
- "httpStatus": { },
- "lastError": { },
- "nextAttemptAt": "string",
- "deliveredAt": { }
}
]
}| id required | string |
{- "id": "string",
- "eventId": "string",
- "endpointId": "string",
- "status": "string",
- "attempts": 0,
- "httpStatus": { },
- "lastError": { },
- "nextAttemptAt": "string",
- "deliveredAt": { }
}| claimToken required | string |
| challengeId required | string Challenge id returned by verify-phone. |
| code required | string 6-digit code from the SMS. |
{- "challengeId": "string",
- "code": "123456"
}{- "challengeId": "string",
- "verified": true
}| claimToken required | string |
| challengeId required | string A VERIFIED phone challenge id for this claim. |
| destinationId required | string One of the caller tenant's ACTIVE payout destination ids. |
{- "challengeId": "string",
- "destinationId": "string"
}{- "paymentId": "string",
- "status": "string",
- "holdReasons": [
- "string"
], - "quotes": [
- {
- "routeId": "string",
- "paymentId": "string",
- "destinationId": "string",
- "provider": "string",
- "sourceAmountBaseUnits": "string",
- "sourceAssetId": "string",
- "destinationAmountMinor": "string",
- "destinationCurrency": "string",
- "fees": { },
- "exchangeRate": "string",
- "estimatedDeliverySeconds": { },
- "speedClass": "INSTANT_EXPECTED",
- "guaranteeLevel": "CONTRACTUAL_SLA",
- "rank": { },
- "requiresBridge": true,
- "requiresConversion": true,
- "requiresPrefunding": true,
- "status": "string",
- "quoteExpiresAt": "string"
}
]
}Returns the RESERVED did:permara identifier for the email or mobile number the invite will go to; sign the payment authorization against it and pay it with the same contact in invite. The same contact always returns the same identity.
string Email the invite goes to. One of email / phone is required. | |
| phone | string Mobile number (E.164) the invite goes to. One of email / phone is required. |
{- "email": "ap@harborgoods.example",
- "phone": "+14155550123"
}{- "did": "did:permara:7f5df4d16e3c8a2e4b1c9d0a3f6e8b7c2d5a4f1e9c8b7a6d5e4f3c2b1a0f9e8d",
- "status": "PROVISIONED",
- "subjectType": "TENANT",
- "verifiedAt": "string",
- "createdAt": "string",
- "version": 0,
- "registryStatus": "string",
- "registryTxHash": "string",
- "documentUri": "string"
}{- "dids": [
- {
- "did": "did:permara:7f5df4d16e3c8a2e4b1c9d0a3f6e8b7c2d5a4f1e9c8b7a6d5e4f3c2b1a0f9e8d",
- "status": "PROVISIONED",
- "subjectType": "TENANT",
- "verifiedAt": "string",
- "createdAt": "string",
- "version": 0,
- "registryStatus": "string",
- "registryTxHash": "string",
- "documentUri": "string"
}
]
}| did required | string |
{- "did": "did:permara:7f5df4d16e3c8a2e4b1c9d0a3f6e8b7c2d5a4f1e9c8b7a6d5e4f3c2b1a0f9e8d",
- "resolvable": true,
- "displayName": "string"
}{- "tenantId": "string",
- "dids": [
- {
- "did": "string",
- "status": "string",
- "subjectType": "string"
}
], - "credentials": [
- {
- "kind": "string",
- "status": "string",
- "expiresAt": "string"
}
], - "destinations": [
- {
- "id": "string",
- "type": "string",
- "status": "string",
- "ownershipStatus": "string",
- "managed": true,
- "asset": "string",
- "network": "string",
- "currency": "string",
- "country": "string",
- "provider": "string",
- "maskedLabel": "string",
- "priority": 0,
- "isDefault": true,
- "allowAutomaticFallback": true
}
]
}Returns the deployment environment, the EVM chains the platform is configured for (with USDC token addresses), and the feature flags that are actually available in this deployment. Computed from config; unbuilt features report false.
{- "apiVersion": "1",
- "environment": "sandbox",
- "chains": [
- {
- "chainId": 84532,
- "name": "Base Sepolia",
- "family": "EVM",
- "testnet": true,
- "usdcAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
- "settlementToken": {
- "symbol": "DUSD",
- "label": "Demo USD",
- "address": "0xDdE94493605c1e64D9D5EE48A9CDA3A86bb4FfC9"
}
}
], - "features": {
- "identity": {
- "sessions": true,
- "provider": "mock",
- "kybProvider": "mock",
- "live": false,
- "kybLive": false,
- "enforcement": "off",
- "signedCredentials": false,
- "presentations": false,
- "authorityEnforcement": "off"
}, - "wallets": true,
- "payments": true,
- "cards": {
- "issuing": true,
- "freeze": true,
- "limits": true
}, - "intents": true,
- "simulate": false,
- "autoramps": false,
- "faucet": true,
- "funding": {
- "mode": "FAUCET",
- "onrampProvider": null
}, - "treasury": false,
- "agents": true,
- "invoices": true,
- "offramp": true,
- "claims": true,
- "destinationRails": true,
- "did": true,
- "envelopes": true,
- "webhooks": false,
- "agreements": false,
- "agreementsAi": {
- "enabled": true,
- "provider": "anthropic",
- "writes": true
}, - "lending": {
- "enabled": true,
- "provider": "mock",
- "chainId": 0
}
}
}Creates the developer/business account that owns API keys and every API-platform resource. Authenticated with a Privy session — this is the one API-platform write that does not need a tenant to already exist. Idempotent: if the caller already owns a tenant, that tenant is returned.
| name | string Human-readable tenant name. Defaults to a generated name. |
| slug | string URL-safe slug (lowercase letters, digits, hyphens). Auto-generated from the name when omitted; a numeric suffix is appended if the slug is taken. |
{- "name": "Acme Robotics",
- "slug": "acme-robotics"
}{- "id": "b3f1c2a0-1111-2222-3333-444455556666",
- "slug": "acme-robotics",
- "name": "Acme Robotics",
- "role": "OWNER",
- "createdAt": "2026-08-09T12:00:00.000Z"
}Returns the tenant the caller is acting as — resolved from the Privy session's membership or from the developer API key.
{- "id": "b3f1c2a0-1111-2222-3333-444455556666",
- "slug": "acme-robotics",
- "name": "Acme Robotics",
- "role": "OWNER",
- "createdAt": "2026-08-09T12:00:00.000Z"
}Creates a PENDING member and returns a one-time invite token (share it with the invitee). They accept via POST /v1/tenants/members/accept, registering the address they will sign with.
| email required | string Invitee email. |
| displayName | string Display name for the member. |
| role | string Default: "MEMBER" Enum: "ADMIN" "MEMBER" |
{- "email": "bob@acme.com",
- "displayName": "Bob Jones",
- "role": "ADMIN"
}{- "id": "string",
- "email": { },
- "displayName": { },
- "role": "MEMBER",
- "status": "PENDING",
- "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
- "privyUserId": { },
- "createdAt": "string",
- "acceptedAt": { },
- "inviteToken": "string"
}{- "members": [
- {
- "id": "string",
- "email": { },
- "displayName": { },
- "role": "MEMBER",
- "status": "PENDING",
- "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
- "privyUserId": { },
- "createdAt": "string",
- "acceptedAt": { }
}
]
}Marks the member REVOKED. Does NOT remove on-chain Safe ownership — the response lists wallets where they are still an owner so you can remove them with an owner-admin tx.
| id required | string |
{- "id": "string",
- "status": "REVOKED",
- "stillOwnerOfWalletIds": [ ]
}Token-authenticated (no API key needed). Activates the member and registers the EVM address they will sign with.
| token required | string The one-time invite token from the invite response. |
| signerAddress required | string The EVM address the member will sign with (their CLI signer or wallet address). Becomes the on-chain owner key when they are added to a Safe. |
| displayName | string Optional display name override. |
{- "token": "string",
- "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
- "displayName": "string"
}{- "id": "string",
- "email": { },
- "displayName": { },
- "role": "MEMBER",
- "status": "PENDING",
- "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
- "privyUserId": { },
- "createdAt": "string",
- "acceptedAt": { }
}| memberId required | string |
| allowedActions required | Array of strings |
| perTxLimitUsd | string |
| dailyLimitUsd | string |
| monthlyLimitUsd | string |
| allowedCurrencies | Array of strings |
| allowedAssets | Array of strings |
| allowedChains | Array of strings |
| allowedDestinationIds | Array of strings |
| approvalGroup | string |
| approvalWeight | number >= 1 |
| requiresCountersignature | boolean |
| countersignAboveUsd | string Countersignature threshold within the per-tx limit. |
| validUntil | string ISO-8601 expiry. |
{- "allowedActions": [
- "payment.create",
- "payment.approve"
], - "perTxLimitUsd": "string",
- "dailyLimitUsd": "string",
- "monthlyLimitUsd": "string",
- "allowedCurrencies": [
- "string"
], - "allowedAssets": [
- "string"
], - "allowedChains": [
- "string"
], - "allowedDestinationIds": [
- "string"
], - "approvalGroup": "string",
- "approvalWeight": 1,
- "requiresCountersignature": true,
- "countersignAboveUsd": "string",
- "validUntil": "string"
}{- "id": "string",
- "memberId": "string",
- "credentialId": { },
- "allowedActions": [
- "string"
], - "perTxLimitUsd": { },
- "dailyLimitUsd": { },
- "monthlyLimitUsd": { },
- "allowedCurrencies": [
- "string"
], - "allowedAssets": [
- "string"
], - "allowedChains": [
- "string"
], - "allowedDestinationIds": [
- "string"
], - "approvalGroup": { },
- "approvalWeight": 0,
- "requiresCountersignature": true,
- "countersignAboveUsd": { },
- "status": "ACTIVE",
- "validFrom": "string",
- "validUntil": { },
- "version": 0,
- "attestation": {
- "message": { },
- "primaryType": "string",
- "note": "string"
}
}| memberId required | string |
| authorityId required | string |
| signature required | string Safe signature blob over the attestation hash (EIP-1271). |
{- "signature": "string"
}{- "id": "string",
- "memberId": "string",
- "credentialId": { },
- "allowedActions": [
- "string"
], - "perTxLimitUsd": { },
- "dailyLimitUsd": { },
- "monthlyLimitUsd": { },
- "allowedCurrencies": [
- "string"
], - "allowedAssets": [
- "string"
], - "allowedChains": [
- "string"
], - "allowedDestinationIds": [
- "string"
], - "approvalGroup": { },
- "approvalWeight": 0,
- "requiresCountersignature": true,
- "countersignAboveUsd": { },
- "status": "ACTIVE",
- "validFrom": "string",
- "validUntil": { },
- "version": 0
}Mints a developer API key for the caller’s tenant. The plaintext key is returned ONCE — store it immediately. Requires the keys:manage scope (Privy sessions and root keys hold it implicitly).
| name required | string Human label for the key. |
| environment | string Enum: "test" "live" Environment. Defaults to |
| scopes | Array of strings Items Enum: "wallets:read" "wallets:write" "wallets:fund" "payments:read" "payments:create" "payments:execute" "cards:read" "cards:issue" "cards:manage" "policies:read" "policies:write" "policies:evaluate" "agents:read" "agents:manage" "treasury:read" "treasury:write" "invoices:read" "invoices:write" "invoices:release" "invoices:pay" "agreements:read" "agreements:write" "agreements:propose" "ramps:read" "ramps:write" "lending:read" "lending:write" "keys:manage" "members:read" "members:manage" "contacts:read" "contacts:write" "identity:read" "identity:write" "status:read" "twofactor:read" "twofactor:manage" "webhooks:manage" "*" Granted permission scopes. Defaults to a read-only set. Use |
| expiresAt | string Optional ISO-8601 expiry. A key past its expiry fails auth. |
| rateLimitPerMinute | number [ 1 .. 10000 ] Per-key rate limit (requests/minute) overriding route defaults. |
| ipAllowlist | Array of strings Source-IP allowlist (exact IPs and IPv4 CIDRs). Non-empty fails CLOSED for other addresses. |
| actingMemberId | string "Acting-as" TenantMember id. Payments created with this key are attributed to that member and run the full member/authority gate (limits, windows, approvals). Omit for a tenant-scoped key (KYB gate only). |
{- "name": "CI sandbox",
- "environment": "test",
- "scopes": [
- "wallets:write",
- "wallets:fund",
- "payments:create"
], - "expiresAt": "2027-01-01T00:00:00.000Z",
- "rateLimitPerMinute": 1,
- "ipAllowlist": [
- "203.0.113.9",
- "10.1.0.0/16"
], - "actingMemberId": "string"
}{- "id": "c1a2b3d4-...",
- "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- "pubId": "Ab12Cd34Ef56",
- "environment": "TEST",
- "scopes": [
- "wallets:write",
- "payments:create"
], - "expiresAt": null,
- "createdAt": "2026-08-09T12:00:00.000Z"
}{- "keys": [
- {
- "id": "c1a2b3d4-...",
- "name": "CI sandbox",
- "pubId": "Ab12Cd34Ef56",
- "environment": "TEST",
- "scopes": [
- "wallets:write"
], - "lastUsedAt": "2026-08-09T12:30:00.000Z",
- "expiresAt": null,
- "revokedAt": null,
- "createdAt": "2026-08-09T12:00:00.000Z"
}
]
}Mints a new secret with the same scopes/environment; the old secret keeps working for a 24-hour grace window, then auto-expires. Returns the new plaintext key once.
| id required | string API key id to rotate. |
{- "id": "c1a2b3d4-...",
- "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- "pubId": "Ab12Cd34Ef56",
- "environment": "TEST",
- "scopes": [
- "wallets:write",
- "payments:create"
], - "expiresAt": null,
- "createdAt": "2026-08-09T12:00:00.000Z"
}Generates the HMAC signing secret — shown ONCE — and, when required is true, makes every @HighRiskOperation route demand a signed request from this key.
| id required | string |
| required | boolean Default: true Require signatures on @HighRiskOperation routes (default true). |
{- "required": true
}{- "keyId": "string",
- "signingSecret": "string",
- "signingRequired": true
}Creates a tenant-owned agent principal.
| name required | string Human label for the agent. |
{- "name": "ap-bot"
}{- "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
- "name": "ap-bot",
- "status": "ACTIVE",
- "createdAt": "2026-08-10T00:00:00.000Z"
}A suspended agent is declined (AGENT_SUSPENDED) on its next action.
| id required | string Agent id |
{- "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
- "name": "ap-bot",
- "status": "ACTIVE",
- "createdAt": "2026-08-10T00:00:00.000Z"
}| id required | string Agent id |
{- "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
- "perTransactionUsd": "50.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00"
}Per-payment / daily / weekly / monthly USD caps enforced on every agent-initiated payment. Only the fields sent change; an explicit null clears a cap.
| id required | string Agent id |
| perTransactionUsd | object or null Per-payment USD cap. |
| dailyUsd | object or null Rolling 24h USD cap. |
| weeklyUsd | object or null Rolling ISO-week USD cap. |
| monthlyUsd | object or null Calendar-month USD cap. |
{- "perTransactionUsd": "50.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00"
}{- "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
- "perTransactionUsd": "50.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00"
}Returns the plaintext key ONCE. Scopes are clamped to the agent ceiling — the key can never hold *, agents:manage, keys:manage, or policies:write.
| id required | string Agent id |
| name required | string Human label for the key. |
| environment | string Enum: "test" "live" Environment. Defaults to |
| scopes | Array of strings Items Enum: "wallets:read" "wallets:write" "wallets:fund" "payments:read" "payments:create" "payments:execute" "cards:read" "cards:issue" "cards:manage" "policies:read" "policies:evaluate" "agents:read" "treasury:read" "invoices:read" "invoices:write" "invoices:release" "invoices:pay" "agreements:read" "agreements:write" "agreements:propose" "ramps:read" "ramps:write" "lending:read" "lending:write" "members:read" "contacts:read" "contacts:write" "identity:read" "status:read" "twofactor:read" Granted scopes. Clamped to the agent ceiling — an agent key can never hold |
| expiresAt | string Optional ISO-8601 expiry. A key past its expiry fails auth. |
{- "name": "ap-bot ci",
- "environment": "test",
- "scopes": [
- "wallets:read",
- "payments:create"
], - "expiresAt": "2027-01-01T00:00:00.000Z"
}{- "id": "c1a2b3d4-...",
- "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- "pubId": "Ab12Cd34Ef56",
- "environment": "TEST",
- "scopes": [
- "wallets:write",
- "payments:create"
], - "expiresAt": null,
- "createdAt": "2026-08-09T12:00:00.000Z"
}Creates a tenant-owned Safe (purpose AGENT) the agent’s card and payments draw from. One wallet per agent; owners are tenant signers (the agent holds no on-chain key). Deploys asynchronously — poll the wallet until DEPLOYED.
| id required | string Agent id |
required | Array of objects (WalletOwnerInput) Safe owners (tenant signers). |
| threshold | number Signature threshold. Defaults to 1. |
| chainId | number EVM chain id. Defaults to the sandbox chain. |
{- "owners": [
- {
- "address": "0x51c2…88",
- "memberId": "string",
- "handle": "string",
- "role": "ADMIN_OWNER",
- "label": "string"
}
], - "threshold": 1,
- "chainId": 84532
}{- "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
- "walletId": "string",
- "address": { },
- "status": "PENDING_DEPLOYMENT",
- "chainId": 84532,
- "threshold": 1
}Issues from the agent’s dedicated wallet (provision it first). Caps omitted from the body are seeded from the agent’s own limits, so the in-prod card gate enforces the agent’s caps synchronously. Sandbox only.
| id required | string Agent id |
| perTransactionUsd | object or null Per-transaction USD cap. |
| dailyUsd | object or null Rolling 24h USD cap. |
| weeklyUsd | object or null Rolling ISO-week USD cap. |
| monthlyUsd | object or null Calendar-month USD cap. |
| blockedMcc | Array of strings MCCs to decline. Replaces the existing list. |
| allowedMcc | Array of strings or null When set, only these MCCs are allowed. |
{- "perTransactionUsd": "250.00",
- "dailyUsd": "500.00",
- "weeklyUsd": "2000.00",
- "monthlyUsd": "5000.00",
- "blockedMcc": [
- "7995"
], - "allowedMcc": [
- "5411",
- "5812"
]
}{- "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
- "stripeCardId": "ic_1NXxxx",
- "last4": "4242",
- "safeAddress": "0x1111111111111111111111111111111111111111",
- "status": "active"
}Newest-first merge of the agent’s payments, card authorizations, and policy decisions. Read-only.
| id required | string Agent id |
| limit | number Example: limit=50 Max items (1–200). Defaults to 50. |
{- "agentId": "string",
- "items": [
- {
- "type": "payment",
- "id": "string",
- "at": "string"
}
]
}Move a reservation from reserved to settled spend at the actual amount (upto ≤ ceiling) once the facilitator confirms the on-chain transfer. Idempotent per nonce.
| nonce required | string The EIP-3009 nonce returned by authorize. |
| txHash required | string Settlement transaction hash. |
| actualAmount | string Actual settled atomic units (upto ≤ ceiling). Defaults to reserved. |
{- "nonce": "string",
- "txHash": "string",
- "actualAmount": "string"
}{- "nonce": "string",
- "status": "SETTLED"
}Creates a Safe for the caller’s tenant and fires the on-chain deploy asynchronously. Returns the predicted CREATE2 address immediately (usable before the proxy is mined). Defaults: Base Sepolia (84532), threshold 1.
| name required | string Human name for the wallet. |
required | Array of objects (WalletOwnerInput) On-chain owners. At least one; the first defaults to ADMIN_OWNER. |
| threshold | number Signature threshold. Defaults to 1 (sandbox single-owner). |
| chainId | number EVM chain id. Defaults to the platform default (Base Sepolia 84532). |
{- "name": "Acme Treasury",
- "owners": [
- {
- "address": "0x51c2…88",
- "memberId": "string",
- "handle": "string",
- "role": "ADMIN_OWNER",
- "label": "string"
}
], - "threshold": 1,
- "chainId": 84532
}{- "id": "string",
- "address": { },
- "status": "PENDING_DEPLOYMENT",
- "chainId": { },
- "threshold": 0,
- "predictedAddress": true,
- "name": "string",
- "owners": [
- {
- "address": "string",
- "role": "string",
- "label": { }
}
], - "balances": [
- {
- "asset": "usdc",
- "amount": "250.00",
- "decimals": 6
}
], - "createdAt": "string"
}Tenant-scoped, newest first.
| skip | string |
| take | string |
{- "wallets": [
- {
- "id": "string",
- "address": { },
- "status": "PENDING_DEPLOYMENT",
- "chainId": { },
- "threshold": 0,
- "predictedAddress": true,
- "name": "string",
- "owners": [
- {
- "address": "string",
- "role": "string",
- "label": { }
}
], - "balances": [
- {
- "asset": "usdc",
- "amount": "250.00",
- "decimals": 6
}
], - "createdAt": "string"
}
], - "total": 0,
- "skip": 0,
- "take": 0
}Pending Safe transactions across your wallets. Pass ?owner=0x… to get only those a specific owner has not yet signed (their co-sign queue).
| owner | string |
{- "pending": [
- {
- "txId": "string",
- "walletId": "string",
- "walletName": "string",
- "to": "string",
- "value": "string",
- "safeTxHash": { },
- "status": "PROPOSED",
- "signatureCount": 0,
- "threshold": 0,
- "createdAt": "string"
}
]
}| txId required | string |
{- "id": "string",
- "walletId": "string",
- "to": "string",
- "value": "string",
- "data": "string",
- "safeTxHash": { },
- "status": "string",
- "signers": [
- "string"
], - "signatureCount": 0,
- "threshold": 0,
- "createdAt": "string"
}Includes live on-chain balances.
| id required | string |
{- "id": "string",
- "address": { },
- "status": "PENDING_DEPLOYMENT",
- "chainId": { },
- "threshold": 0,
- "predictedAddress": true,
- "name": "string",
- "owners": [
- {
- "address": "string",
- "role": "string",
- "label": { }
}
], - "balances": [
- {
- "asset": "usdc",
- "amount": "250.00",
- "decimals": 6
}
], - "createdAt": "string"
}Builds and pins a SafeTx (to/value/data). Returns the safeTxHash to sign.
| id required | string |
| to required | string Destination contract/EOA (EIP-55). |
| value | string Native value in wei (decimal string). Defaults to "0". |
| data | string Calldata hex. Defaults to 0x. |
| ownerAddress | string Owner address to act as (must be a registered on-chain owner). Optional when the wallet has exactly one on-chain owner. |
{- "to": "0x036CbD…",
- "value": "0",
- "data": "0xa9059cbb…",
- "ownerAddress": "string"
}The signer is recovered from the raw secp256k1 signature over the safeTxHash and must be a registered on-chain owner. When the threshold is met the tx becomes executable.
| txId required | string |
| signature required | string Raw secp256k1 signature over the 32-byte safeTxHash (NOT personal_sign). |
{- "signature": "0x…"
}| txId required | string |
| ownerAddress | string Owner address to act as. Optional for single-owner wallets. |
{- "ownerAddress": "string"
}| txId required | string |
| ownerAddress | string Owner address to act as. Optional for single-owner wallets. |
{- "ownerAddress": "string"
}Proposes an owner-admin SafeTx; the wallet threshold of owners must sign it.
| id required | string |
| newOwner required | string New owner address (EIP-55). |
| threshold required | number Resulting signature threshold (1..ownerCount+1). |
| role | string Enum: "ADMIN_OWNER" "FINANCE_OWNER" "MERCHANT_OPERATOR" DB role for the new owner (default FINANCE_OWNER). |
| ownerAddress | string Acting owner (ADMIN_OWNER). Optional if sole owner. |
{- "newOwner": "string",
- "threshold": 2,
- "role": "ADMIN_OWNER",
- "ownerAddress": "string"
}| id required | string |
| addr required | string Owner address to remove |
| threshold required | number Resulting signature threshold (1..ownerCount-1). |
| ownerAddress | string Acting owner (ADMIN_OWNER). Optional if sole owner. |
{- "threshold": 1,
- "ownerAddress": "string"
}| id required | string |
| addr required | string Existing owner address to replace |
| newOwner required | string The replacement owner address (EIP-55). |
| ownerAddress | string Acting owner (ADMIN_OWNER). Optional if sole owner. |
{- "newOwner": "string",
- "ownerAddress": "string"
}| id required | string |
| threshold required | number New signature threshold (1..ownerCount). |
| ownerAddress | string Acting owner (ADMIN_OWNER). Optional if sole owner. |
{- "threshold": 2,
- "ownerAddress": "string"
}Both holders on the configured chain in Demo USD (testnet) or USDC (mainnet). ensure=true provisions the org account and links the smart account when missing.
| ensure | string Enum: "true" "false" |
{- "chainId": 84532,
- "chainName": "Base Sepolia",
- "testnet": true,
- "asset": {
- "symbol": "DUSD",
- "label": "Demo USD",
- "address": "0xDdE94493605c1e64D9D5EE48A9CDA3A86bb4FfC9",
- "decimals": 6
}, - "primary": "SMART_ACCOUNT",
- "accounts": [
- {
- "kind": "SMART_ACCOUNT",
- "address": { },
- "walletId": { },
- "status": "READY",
- "amountBaseUnits": { },
- "amountUsd": "250.000000"
}
], - "funding": "FAUCET",
- "partial": true,
- "observedAt": "2026-09-16T12:00:00.000Z"
}Sends platform-funded test USDC (default) or test ETH to the wallet. TEST environment only; capped at 1000 USDC / 0.02 ETH per drip and rate-limited per wallet and tenant.
| id required | string Wallet id to fund. |
| asset | string Enum: "usdc" "eth" Asset to drip. Defaults to |
| amount | string Human decimal amount (e.g. "250" USDC, "0.01" ETH). Defaults to a per-asset default. Capped at 1000 USDC / 0.02 ETH per drip. |
{- "asset": "usdc",
- "amount": "250"
}{- "id": "d1a2b3c4-...",
- "walletId": "w1",
- "account": "SMART_ACCOUNT",
- "toAddress": "0x…",
- "asset": "usdc",
- "amount": "250",
- "chainId": 84532,
- "status": "SUBMITTED",
- "txHash": { },
- "failureReason": { },
- "createdAt": "2026-08-09T12:00:00.000Z"
}Mints Demo USD to the member's smart account (default) or the organization's Safe on a testnet chain. Same caps and rate limits as the wallet route; FAUCET_NOT_AVAILABLE on a mainnet chain.
| asset | string Enum: "usdc" "eth" Asset to drip. Defaults to |
| amount | string Human decimal amount (e.g. "250" USDC, "0.01" ETH). Defaults to a per-asset default. Capped at 1000 USDC / 0.02 ETH per drip. |
| account | string Enum: "SMART_ACCOUNT" "ORG_MULTISIG" Which account to fund: the member's smart account or the organization's Safe. Defaults to the primary account from GET /v1/balance. |
{- "asset": "usdc",
- "amount": "250",
- "account": "SMART_ACCOUNT"
}{- "id": "d1a2b3c4-...",
- "walletId": "w1",
- "account": "SMART_ACCOUNT",
- "toAddress": "0x…",
- "asset": "usdc",
- "amount": "250",
- "chainId": 84532,
- "status": "SUBMITTED",
- "txHash": { },
- "failureReason": { },
- "createdAt": "2026-08-09T12:00:00.000Z"
}Tenant-scoped, newest first.
| walletId | string |
{- "drips": [
- {
- "id": "d1a2b3c4-...",
- "walletId": "w1",
- "account": "SMART_ACCOUNT",
- "toAddress": "0x…",
- "asset": "usdc",
- "amount": "250",
- "chainId": 84532,
- "status": "SUBMITTED",
- "txHash": { },
- "failureReason": { },
- "createdAt": "2026-08-09T12:00:00.000Z"
}
]
}{- "id": "d1a2b3c4-...",
- "walletId": "w1",
- "account": "SMART_ACCOUNT",
- "toAddress": "0x…",
- "asset": "usdc",
- "amount": "250",
- "chainId": 84532,
- "status": "SUBMITTED",
- "txHash": { },
- "failureReason": { },
- "createdAt": "2026-08-09T12:00:00.000Z"
}Exact match only. Email resolution requires the target to have opted in.
| handle | string |
string |
{- "handle": "acme-treasury",
- "displayName": { },
- "address": "0x7Fb2…c41A",
- "chainId": 84532,
- "verified": true
}Points an @handle at one of your wallets so others can pay you by name.
| handle required | string Handle to claim (without the @). |
| walletId required | string Wallet id this handle resolves to. |
| discoverableByEmail | boolean Opt in to email-based resolution. |
string Contact email for email resolution. |
{- "handle": "acme-treasury",
- "walletId": "w1",
- "discoverableByEmail": false,
- "email": "string"
}{- "handle": "acme-treasury",
- "displayName": { },
- "address": "0x7Fb2…c41A",
- "chainId": 84532,
- "verified": true
}| label required | string Short label used as |
| displayName | string |
| notes | string |
required | object (ContactDestinationInput) |
{- "label": "acme",
- "displayName": "Acme Robotics",
- "notes": "string",
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}
}{- "id": "string",
- "label": "string",
- "displayName": { },
- "notes": { },
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}, - "createdAt": "string"
}{- "contacts": [
- {
- "id": "string",
- "label": "string",
- "displayName": { },
- "notes": { },
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}, - "createdAt": "string"
}
]
}{- "id": "string",
- "label": "string",
- "displayName": { },
- "notes": { },
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}, - "createdAt": "string"
}| id required | string |
| displayName | string |
| notes | string |
object (ContactDestinationInput) |
{- "displayName": "string",
- "notes": "string",
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}
}{- "id": "string",
- "label": "string",
- "displayName": { },
- "notes": { },
- "destination": {
- "type": "handle",
- "handle": "string",
- "address": "string",
- "email": "string",
- "walletId": "string",
- "chainId": 0
}, - "createdAt": "string"
}| kind required | string Enum: "KYC" "KYB" KYC verifies a member; KYB the tenant. |
| memberId | string TenantMember id — required for KYC, ignored for KYB. |
| legalName | string Subject legal name. Defaults to the member display name (KYC) or tenant name (KYB). |
string Subject contact email; defaults to the member email. | |
| country | string ISO-3166 alpha-2 country code. |
{- "kind": "KYC",
- "memberId": "string",
- "legalName": "string",
- "email": "string",
- "country": "DE"
}{- "id": "string",
- "kind": "KYC",
- "subjectType": "TENANT",
- "subjectId": "string",
- "legalName": "string",
- "status": "CREATED",
- "requirements": [
- {
- "type": "authorized_representative_kyc",
- "status": "PENDING",
- "subjectRef": "string"
}
], - "credentialId": { },
- "client": {
- "provider": "persona",
- "sessionRef": "string",
- "token": "string",
- "templateId": "string",
- "environmentId": "string"
}, - "createdAt": "string",
- "updatedAt": "string",
- "completedAt": { }
}| subject_type required | string |
| subject_id required | string |
{- "sessions": [
- {
- "id": "string",
- "kind": "KYC",
- "subjectType": "TENANT",
- "subjectId": "string",
- "legalName": "string",
- "status": "CREATED",
- "requirements": [
- {
- "type": "authorized_representative_kyc",
- "status": "PENDING",
- "subjectRef": "string"
}
], - "credentialId": { },
- "client": {
- "provider": "persona",
- "sessionRef": "string",
- "token": "string",
- "templateId": "string",
- "environmentId": "string"
}, - "createdAt": "string",
- "updatedAt": "string",
- "completedAt": { }
}
]
}| id required | string |
{- "id": "string",
- "kind": "KYC",
- "subjectType": "TENANT",
- "subjectId": "string",
- "legalName": "string",
- "status": "CREATED",
- "requirements": [
- {
- "type": "authorized_representative_kyc",
- "status": "PENDING",
- "subjectRef": "string"
}
], - "credentialId": { },
- "client": {
- "provider": "persona",
- "sessionRef": "string",
- "token": "string",
- "templateId": "string",
- "environmentId": "string"
}, - "createdAt": "string",
- "updatedAt": "string",
- "completedAt": { }
}| id required | string |
{- "id": "string",
- "kind": "KYC",
- "subjectType": "TENANT",
- "subjectId": "string",
- "legalName": "string",
- "status": "CREATED",
- "requirements": [
- {
- "type": "authorized_representative_kyc",
- "status": "PENDING",
- "subjectRef": "string"
}
], - "credentialId": { },
- "client": {
- "provider": "persona",
- "sessionRef": "string",
- "token": "string",
- "templateId": "string",
- "environmentId": "string"
}, - "createdAt": "string",
- "updatedAt": "string",
- "completedAt": { }
}| id required | string |
{- "id": "string",
- "kind": "KYC",
- "subjectType": "TENANT",
- "subjectId": "string",
- "legalName": "string",
- "status": "CREATED",
- "requirements": [
- {
- "type": "authorized_representative_kyc",
- "status": "PENDING",
- "subjectRef": "string"
}
], - "credentialId": { },
- "client": {
- "provider": "persona",
- "sessionRef": "string",
- "token": "string",
- "templateId": "string",
- "environmentId": "string"
}, - "createdAt": "string",
- "updatedAt": "string",
- "completedAt": { }
}{- "identities": [
- {
- "id": "string",
- "did": "did:safebank:cabc…",
- "identityType": "PERSON",
- "status": "ACTIVE",
- "subjectType": "TENANT",
- "subjectId": "string",
- "primarySmartAccountId": { },
- "credentialAssuranceLevel": { },
- "createdAt": "string"
}
]
}| subjectType required | string Enum: "TENANT" "TENANT_MEMBER" TENANT = this organization; TENANT_MEMBER needs memberId. |
| memberId | string TenantMember id — required for TENANT_MEMBER. |
{- "subjectType": "TENANT",
- "memberId": "string"
}{- "id": "string",
- "did": "did:safebank:cabc…",
- "identityType": "PERSON",
- "status": "ACTIVE",
- "subjectType": "TENANT",
- "subjectId": "string",
- "primarySmartAccountId": { },
- "credentialAssuranceLevel": { },
- "createdAt": "string"
}{- "id": "string",
- "did": "did:safebank:cabc…",
- "identityType": "PERSON",
- "status": "ACTIVE",
- "subjectType": "TENANT",
- "subjectId": "string",
- "primarySmartAccountId": { },
- "credentialAssuranceLevel": { },
- "createdAt": "string"
}| id required | string |
{- "wallets": [
- {
- "id": "string",
- "identityId": "string",
- "chainFamily": "string",
- "chainId": { },
- "walletAddress": "string",
- "walletType": "EOA",
- "controllerType": "SELF",
- "verificationMethod": "SIGNATURE_CHALLENGE",
- "status": "PENDING",
- "validFrom": "string",
- "validUntil": { },
- "verifiedAt": { }
}
]
}| id required | string |
| walletAddress required | string EVM address to bind (checksummed at rest). |
| chainId | number EVM chain id the binding is scoped to. |
| walletType | string Enum: "EOA" "SMART_ACCOUNT" "MULTISIG_SAFE" |
{- "walletAddress": "string",
- "chainId": 0,
- "walletType": "EOA"
}{- "id": "string",
- "identityId": "string",
- "chainFamily": "string",
- "chainId": { },
- "walletAddress": "string",
- "walletType": "EOA",
- "controllerType": "SELF",
- "verificationMethod": "SIGNATURE_CHALLENGE",
- "status": "PENDING",
- "validFrom": "string",
- "validUntil": { },
- "verifiedAt": { },
- "challenge": "string"
}| id required | string |
| bindingId required | string |
| signature required | string EIP-191 signature over the returned challenge. |
{- "signature": "string"
}{- "id": "string",
- "identityId": "string",
- "chainFamily": "string",
- "chainId": { },
- "walletAddress": "string",
- "walletType": "EOA",
- "controllerType": "SELF",
- "verificationMethod": "SIGNATURE_CHALLENGE",
- "status": "PENDING",
- "validFrom": "string",
- "validUntil": { },
- "verifiedAt": { }
}| id required | string |
| bindingId required | string |
| newWalletAddress required | string The replacement wallet address. |
{- "newWalletAddress": "string"
}{- "id": "string",
- "identityId": "string",
- "chainFamily": "string",
- "chainId": { },
- "walletAddress": "string",
- "walletType": "EOA",
- "controllerType": "SELF",
- "verificationMethod": "SIGNATURE_CHALLENGE",
- "status": "PENDING",
- "validFrom": "string",
- "validUntil": { },
- "verifiedAt": { },
- "challenge": "string"
}Returns {key, value, salt, leaf, proof[], root} for exactly one claim of the credential. A verifier checks it off-chain (verifyClaimProof) or on-chain (CredentialRegistry.verifyClaim) against the anchored root — every other claim stays a hash. 404 DISCLOSURE_NOT_AVAILABLE until the credential is anchored.
| id required | string |
| claim required | string |
| subject_type required | string |
| subject_id required | string |
{- "credentials": [
- {
- "id": "string",
- "kind": "PERSON_IDENTITY",
- "subjectType": "TENANT",
- "subjectId": "string",
- "status": "ACTIVE",
- "legalName": "string",
- "issuedAt": "string",
- "expiresAt": { },
- "revokedAt": { },
- "revokedReason": { },
- "subjectDid": { },
- "credentialHash": { },
- "issuerKind": "PLATFORM"
}
]
}{- "id": "string",
- "kind": "PERSON_IDENTITY",
- "subjectType": "TENANT",
- "subjectId": "string",
- "status": "ACTIVE",
- "legalName": "string",
- "issuedAt": "string",
- "expiresAt": { },
- "revokedAt": { },
- "revokedReason": { },
- "subjectDid": { },
- "credentialHash": { },
- "issuerKind": "PLATFORM"
}| id required | string |
{- "id": "string",
- "status": "ACTIVE",
- "revokedReason": { },
- "statusRefreshedAt": { },
- "statusSource": { }
}| id required | string |
{- "id": "string",
- "document": { },
- "signature": "string",
- "credentialHash": "string",
- "nonce": "string",
- "issuerRef": "string",
- "schemaVersion": "string"
}| type | string Enum: "ONCHAIN_WALLET" "PAYPAL" "VENMO" "US_BANK_ACH" "SEPA" "SAFEBANK_BALANCE" Defaults to ONCHAIN_WALLET when an address is supplied (legacy shape). |
| asset | string Asset symbol (on-chain types). |
| network | string Network key, lowercase (on-chain types). |
| address | string Receiving address, stored verbatim (case-sensitive). |
string PayPal email. | |
| phone | string E.164 phone (PayPal/Venmo). |
| handle | string Venmo handle (without @). |
| routingNumber | string US ABA routing number (US_BANK_ACH). |
| accountNumber | string US bank account number (US_BANK_ACH). |
| iban | string IBAN (SEPA). |
| country | string ISO-3166 alpha-2 country. |
| currency | string ISO-4217 payout currency (fiat rails). |
| label | string Display label override. |
{- "type": "ONCHAIN_WALLET",
- "asset": "USDT",
- "network": "tron",
- "address": "string",
- "email": "string",
- "phone": "string",
- "handle": "string",
- "routingNumber": "string",
- "accountNumber": "string",
- "iban": "string",
- "country": "string",
- "currency": "string",
- "label": "string"
}{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}{- "destinations": [
- {
- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}
]
}| id required | string |
{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}| id required | string |
| label | string Display label. |
| priority | number Ordering preference among own destinations. |
| allowAutomaticFallback | boolean Consent to automatic fallback routing to this destination (spec rule 14). |
{- "label": "string",
- "priority": 0,
- "allowAutomaticFallback": true
}{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}| id required | string |
{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}| id required | string |
{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}| id required | string |
| signature | string EIP-712 DestinationOwnership signature by the key controlling the destination address (production proof; EVM only). Required when nonce or expiresAt is supplied. |
| nonce | string Single-use nonce (uint256 decimal string). Required when signature is supplied. |
| expiresAt | string Unix-seconds expiry of the proof. Required when signature is supplied. |
{- "signature": "string",
- "nonce": "string",
- "expiresAt": "string"
}{- "id": "string",
- "type": "STABLECOIN_ADDRESS",
- "asset": { },
- "network": { },
- "address": { },
- "provider": { },
- "country": { },
- "currency": { },
- "maskedLabel": "string",
- "status": "PENDING_VERIFICATION",
- "ownershipStatus": "DECLARED",
- "verificationCredentialId": { },
- "priority": 0,
- "allowAutomaticFallback": true,
- "isDefault": true,
- "consentedAt": { },
- "verifiedAt": { },
- "revokedAt": { },
- "createdAt": "string"
}| purpose required | string What the presentation authorizes. |
| identityId | string Expected holder identity, when known. |
| paymentId | string Payment the presentation is scoped to. |
{- "purpose": "payment.approve",
- "identityId": "string",
- "paymentId": "string"
}{- "nonce": "string",
- "audience": "string",
- "domainTag": "string",
- "purpose": "string",
- "expiresAt": "string"
}| nonce required | string |
| holderDid required | string |
| signature required | string EIP-712 CredentialPresentation signature (hex). |
| signerAddress required | string The bound wallet that signed. |
| credentialIds required | Array of strings Credential ids being presented. |
| expiresAt required | string ISO-8601 expiry the holder signed. |
{- "nonce": "string",
- "holderDid": "did:safebank:cabc…",
- "signature": "string",
- "signerAddress": "string",
- "credentialIds": [
- "string"
], - "expiresAt": "string"
}{- "verified": true,
- "holderDid": "string",
- "credentialResults": [
- {
- "credentialId": "string",
- "credentialHash": "string",
- "verdict": "VALID"
}
], - "reasonCodes": [
- "string"
], - "presentationId": "string"
}| action required | string Enum: "payments.create" "invoices.pay" "ramps.offramp" "claims.claim" |
{- "action": "payments.create"
}{- "id": "string",
- "subjectAddress": "string",
- "schema": "string",
- "mode": "synthetic",
- "maxPrincipal": "string",
- "riskTier": 0,
- "profile": { },
- "permitDigest": "string",
- "issuerAddress": "string",
- "expiresAt": "string",
- "status": "string"
}| rules required | object Structured rules: maximumFeeMinor, maximumAmountUsd, allowedRails, allowedAssets, allowedChains, approvals[{aboveUsd, minimumApprovals}]. Unknown keys are refused. |
{- "rules": { }
}{- "policyId": { },
- "version": 0,
- "rules": { },
- "status": "ACTIVE",
- "credentialId": { },
- "activatedAt": { },
- "attestation": {
- "message": { },
- "primaryType": "string",
- "note": "string"
}
}| signature required | string Safe signature blob over the attestation hash (EIP-1271). |
{- "signature": "string"
}{- "policyId": { },
- "version": 0,
- "rules": { },
- "status": "ACTIVE",
- "credentialId": { },
- "activatedAt": { }
}Compiles the document to an immutable v1 (IR + sha256) and makes it active.
| name required | string Human name for the policy. |
| document required | object The policy document (schemaVersion 1): limits (per-txn/daily/weekly/monthly USD), mcc (blocked/allowed), counterparties (blocked). Compiled to an immutable versioned IR. |
{- "name": "AP bot guardrails",
- "document": {
- "schemaVersion": 1,
- "limits": {
- "perTransactionUsd": "250.00",
- "dailyUsd": "1000.00"
}, - "mcc": {
- "blocked": [
- "7995"
]
}
}
}{- "policyId": "string",
- "name": "string",
- "status": "ACTIVE",
- "activeVersionId": { },
- "activeVersion": { },
- "createdAt": "string"
}Deterministically tests a hypothetical transaction against a policy (by id or by the policy attached to a subject) using the same engine that gates live authorizations. Returns allow/deny + a per-rule trace and writes a DecisionLog audit row.
| policyId | string Evaluate a specific policy id (else the one attached to the subject). |
| subjectType | string Enum: "wallet" "card" "agent" "treasury_account" Resolve the attached policy. |
| subjectId | string |
| amountUsd required | string Transaction USD amount to test. |
| mcc | string 4-digit MCC to test. |
| counterparty | string Counterparty address to test. |
{- "policyId": "string",
- "subjectType": "wallet",
- "subjectId": "string",
- "amountUsd": "120.00",
- "mcc": "5411",
- "counterparty": "string"
}{- "allow": true,
- "reason": { },
- "policyId": { },
- "policyVersion": { },
- "sha256": { },
- "ruleTrace": [
- {
- "rule": "PER_TXN_LIMIT",
- "result": "pass",
- "detail": { }
}
], - "decisionLogId": "string"
}Appends an immutable version and makes it the active one.
| id required | string |
| document required | object A new document — committed as the next immutable version. |
{- "document": { }
}{- "versionId": "string",
- "version": 0,
- "sha256": "string",
- "ir": { },
- "createdAt": "string"
}Binds the policy to a wallet / card / agent / treasury account. One active policy per subject. Attachments scope dry-run evaluation today; live gating is a later increment.
| id required | string |
| subjectType required | string Enum: "wallet" "card" "agent" "treasury_account" |
| subjectId required | string Id of the wallet / card / agent / treasury account. |
{- "subjectType": "wallet",
- "subjectId": "string"
}{- "attachmentId": "string",
- "policyId": "string",
- "subjectType": "wallet",
- "subjectId": "string",
- "attachedAt": "string"
}{- "factors": [
- {
- "id": "string",
- "type": "EMAIL",
- "status": "PENDING",
- "label": { },
- "hint": "string",
- "verifiedAt": { },
- "usableAt": { },
- "usableNow": true,
- "lastUsedAt": { },
- "createdAt": "string"
}
], - "requiredFactors": 0,
- "usableFactors": 0
}Sends a confirmation code (EMAIL/SMS) or returns a TOTP secret. The factor stays PENDING until POST /v1/2fa/factors/{id}/verify proves control of the channel.
| type required | string Enum: "EMAIL" "SMS" "TOTP" "PRIVY_MFA" |
string Required when type=EMAIL. | |
| phoneE164 | string Required when type=SMS. E.164, e.g. +15551234567. |
| label | string Optional friendly name, e.g. "work phone". |
{- "type": "EMAIL",
- "email": "string",
- "phoneE164": "string",
- "label": "string"
}{- "factorId": "string",
- "type": "EMAIL",
- "status": "string",
- "hint": "string",
- "secretBase32": "string",
- "otpauthUri": "string",
- "signerAddress": "string"
}| factorId required | string |
| code | string 6-digit code (EMAIL / SMS / TOTP). |
| signature | string EIP-712 signature (PRIVY_MFA). |
{- "code": "string",
- "signature": "string"
}{- "id": "string",
- "type": "EMAIL",
- "status": "PENDING",
- "label": { },
- "hint": "string",
- "verifiedAt": { },
- "usableAt": { },
- "usableNow": true,
- "lastUsedAt": { },
- "createdAt": "string"
}Effective immediately. Refused if it would drop your usable factors below the tenant requirement, or leave you with only email/SMS (which would make your funds unreachable during a provider outage).
| factorId required | string |
Also used to resend. The message states the amount and destination — that is the anti-phishing control, so compare it against what you are actually sending.
| challengeId required | string |
| factorId required | string Which enrolled factor to deliver the code to. |
{- "factorId": "string"
}Repeat until satisfiedFactors reaches requiredFactors, then replay the original request with the X-SafeBank-2FA-Challenge header.
| challengeId required | string |
| factorId required | string |
| code | string 6-digit code (EMAIL / SMS / TOTP). |
| signature | string EIP-712 signature (PRIVY_MFA). |
{- "factorId": "string",
- "code": "string",
- "signature": "string"
}Owner/admin user sessions only — never an API key, whatever scopes it holds. The cooling-off window cannot be set below 24h while protection is enabled.
| enabled | boolean |
| coolingOffSeconds | number >= 86400 Minimum 86400 (24h) while enabled. |
| thresholdUsd | string |
| requiredFactors | number >= 1 |
{- "enabled": true,
- "coolingOffSeconds": 86400,
- "thresholdUsd": "100",
- "requiredFactors": 1
}{- "enabled": true,
- "coolingOffSeconds": 0,
- "thresholdUsd": "string",
- "requiredFactors": 0,
- "updatedAt": { }
}Creates one Safe per bucket (202 — CREATE2 addresses are usable immediately, deployment is async). Sandbox-only for now.
| name required | string Treasury name. |
required | Array of objects (WalletOwnerInput) Safe owners applied to every bucket wallet. |
| threshold | number Signature threshold per bucket Safe. Defaults to 1. |
| chainId | number EVM chain id. Defaults to Base Sepolia (84532). |
required | Array of objects (TreasuryBucketInput) 1-8 buckets, one Safe each. |
{- "name": "Acme Treasury",
- "owners": [
- {
- "address": "0x51c2…88",
- "memberId": "string",
- "handle": "string",
- "role": "ADMIN_OWNER",
- "label": "string"
}
], - "threshold": 0,
- "chainId": 0,
- "buckets": [
- {
- "name": "Operating",
- "kind": "OPERATING",
- "targetBps": 6000,
- "apyBps": 450
}
]
}{- "accountId": "string",
- "name": "string",
- "buckets": [
- {
- "bucketId": "string",
- "name": "string",
- "kind": "OPERATING",
- "targetBps": 0,
- "apyBps": { },
- "walletId": "string",
- "safeAddress": { },
- "walletStatus": "string",
- "balanceUsd": { },
- "driftBps": { },
- "accruedYieldUsd": "string",
- "simulatedYield": true
}
], - "totalUsd": { },
- "createdAt": "string"
}Live bucket balances, drift vs targetBps, and accrued simulated yield. A bucket whose balance cannot be read right now reports null (never zero).
| id required | string |
{- "accountId": "string",
- "name": "string",
- "buckets": [
- {
- "bucketId": "string",
- "name": "string",
- "kind": "OPERATING",
- "targetBps": 0,
- "apyBps": { },
- "walletId": "string",
- "safeAddress": { },
- "walletStatus": "string",
- "balanceUsd": { },
- "driftBps": { },
- "accruedYieldUsd": "string",
- "simulatedYield": true
}
], - "totalUsd": { },
- "createdAt": "string"
}| id required | string |
| type required | string Enum: "SWEEP_EXCESS" "TOP_UP" "REBALANCE_TO_TARGET" |
| sourceBucketId | string Source bucket id (SWEEP_EXCESS / TOP_UP). |
| destBucketId | string Destination bucket id (SWEEP_EXCESS / TOP_UP). |
| thresholdUsd | string SWEEP_EXCESS: balance above this is swept. TOP_UP: trigger level (defaults to targetUsd). |
| targetUsd | string TOP_UP: refill the destination back up to this level. |
| intervalSeconds | number Minimum seconds between fires. Default 3600. |
| enabled | boolean Rules are enabled by default. |
{- "type": "SWEEP_EXCESS",
- "sourceBucketId": "string",
- "destBucketId": "string",
- "thresholdUsd": "1000.00",
- "targetUsd": "500.00",
- "intervalSeconds": 0,
- "enabled": true
}{- "ruleId": "string",
- "accountId": "string",
- "type": "SWEEP_EXCESS",
- "sourceBucketId": { },
- "destBucketId": { },
- "thresholdUsd": { },
- "targetUsd": { },
- "intervalSeconds": 0,
- "enabled": true,
- "lastFiredAt": { },
- "createdAt": "string"
}{- "rules": [
- {
- "ruleId": "string",
- "accountId": "string",
- "type": "SWEEP_EXCESS",
- "sourceBucketId": { },
- "destBucketId": { },
- "thresholdUsd": { },
- "targetUsd": { },
- "intervalSeconds": 0,
- "enabled": true,
- "lastFiredAt": { },
- "createdAt": "string"
}
], - "total": 0
}| ruleId required | string |
| thresholdUsd | string |
| targetUsd | string |
| intervalSeconds | number |
| enabled | boolean |
{- "thresholdUsd": "string",
- "targetUsd": "string",
- "intervalSeconds": 0,
- "enabled": true
}{- "ruleId": "string",
- "accountId": "string",
- "type": "SWEEP_EXCESS",
- "sourceBucketId": { },
- "destBucketId": { },
- "thresholdUsd": { },
- "targetUsd": { },
- "intervalSeconds": 0,
- "enabled": true,
- "lastFiredAt": { },
- "createdAt": "string"
}Proposes a bucket-to-bucket USDC Payment. Execution requires owner signatures via the payments API (a 1-of-1 Safe completes in a single sign call).
| id required | string |
| sourceBucketId required | string Bucket to move USDC out of. |
| destBucketId required | string Bucket to move USDC into. |
| amountUsd required | string USD amount to move. |
| ownerAddress | string Acting owner for the proposal (required when the Safe has multiple owners). |
{- "sourceBucketId": "string",
- "destBucketId": "string",
- "amountUsd": "250.00",
- "ownerAddress": "string"
}{- "sweepId": "string",
- "accountId": "string",
- "ruleId": { },
- "sourceBucketId": "string",
- "destBucketId": "string",
- "amountUsd": "string",
- "status": "PROPOSED",
- "paymentId": { },
- "paymentStatus": { },
- "failureReason": { },
- "createdAt": "string"
}Includes the live status of each sweep’s linked payment.
| id required | string |
{- "sweeps": [
- {
- "sweepId": "string",
- "accountId": "string",
- "ruleId": { },
- "sourceBucketId": "string",
- "destBucketId": "string",
- "amountUsd": "string",
- "status": "PROPOSED",
- "paymentId": { },
- "paymentStatus": { },
- "failureReason": { },
- "createdAt": "string"
}
], - "total": 0
}on = credit the wallet Safe with USDC (fiat debit simulated; completes immediately). off = propose a Safe debit to the liquidation address — owners sign the linked payment and the (simulated) fiat payout confirms when it executes. Sandbox-only.
| walletId required | string Wallet whose Safe is credited (on) or debited (off). |
| direction required | string Enum: "on" "off" on = fiat->USDC, off = USDC->fiat. |
| amount required | string USD amount. |
| provider | string Default: "simulated" Enum: "simulated" "privy" "stripe" "visa" "ousd" Ramp provider. Only |
{- "walletId": "string",
- "direction": "on",
- "amount": "100.00",
- "provider": "simulated"
}{- "rampId": "string",
- "walletId": "string",
- "direction": "ON",
- "provider": "simulated",
- "amountUsd": "string",
- "status": "SUBMITTED",
- "txHash": { },
- "paymentId": { },
- "paymentStatus": { },
- "fiatRef": { },
- "simulated": true,
- "failureReason": { },
- "createdAt": "string"
}{- "ramps": [
- {
- "rampId": "string",
- "walletId": "string",
- "direction": "ON",
- "provider": "simulated",
- "amountUsd": "string",
- "status": "SUBMITTED",
- "txHash": { },
- "paymentId": { },
- "paymentStatus": { },
- "fiatRef": { },
- "simulated": true,
- "failureReason": { },
- "createdAt": "string"
}
], - "total": 0
}{- "rampId": "string",
- "walletId": "string",
- "direction": "ON",
- "provider": "simulated",
- "amountUsd": "string",
- "status": "SUBMITTED",
- "txHash": { },
- "paymentId": { },
- "paymentStatus": { },
- "fiatRef": { },
- "simulated": true,
- "failureReason": { },
- "createdAt": "string"
}| payeeName | string Human label for the payee. |
| description | string What the invoice is for. |
| amountUsd required | string Amount due, USD. |
| payerAddress required | string Payer address (funds the hold Safe). |
| payeeAddress required | string Payee address (receives a release). |
| arbiterAddress | string Platform arbiter address (tie-break owner). Defaults to the platform arbiter. |
| chainId | number EVM chain id. Defaults to Base Sepolia (84532). |
| expiresAt | string ISO-8601 auto-expiry for the unfunded invoice. |
{- "payeeName": "Volt Components",
- "description": "string",
- "amountUsd": "120.00",
- "payerAddress": "0x1111…",
- "payeeAddress": "0x2222…",
- "arbiterAddress": "string",
- "chainId": 0,
- "expiresAt": "string"
}{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}{- "invoices": [
- {
- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}
], - "total": 0
}The caller is the sender: targets the recipient by @handle or wallet address and carries an EIP-712 InvoiceAuthorization signed by a registered member key.
| toHandle | string Recipient's Permara @handle (or use toAddress). |
| toAddress | string Recipient's wallet address (or use toHandle). |
| amountUsd required | string Amount due, USD. |
| payeeAddress required | string Address that receives payment (the sender). |
| payeeName | string Human label for the payee (bound by docHash). |
| description | string What the bill is for (bound by docHash). |
| chainId | number EVM chain id. Defaults to the payer wallet chain. |
| senderAddress required | string Address that SIGNED the authorization (a member key). |
| signature required | string EIP-712 InvoiceAuthorization signature. |
| sigNonce required | string Single-use replay nonce (uint256 as a decimal string). |
| sigExpiresAt required | string ISO-8601 authorization expiry. |
| sigDocHash | string sha256 of the signed human-readable terms (bytes32). |
| domainChainId | number EIP-712 domain chainId (defaults to the bill chainId). |
| domainVerifyingContract | string EIP-712 domain verifyingContract anchor. |
{- "toHandle": "string",
- "toAddress": "string",
- "amountUsd": "120.00",
- "payeeAddress": "string",
- "payeeName": "string",
- "description": "string",
- "chainId": 0,
- "senderAddress": "string",
- "signature": "string",
- "sigNonce": "string",
- "sigExpiresAt": "string",
- "sigDocHash": "string",
- "domainChainId": 0,
- "domainVerifyingContract": "string"
}{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}| verification | string Enum: "UNVERIFIED" "VERIFIED" "FAILED" |
{- "bills": [
- {
- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}
], - "total": 0
}{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}Provisions the 2-of-3 hold Safe (202 — async deploy) and returns funding info.
| id required | string |
{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}| id required | string |
| evidence | string Delivery evidence (note / URL / reference). |
{- "evidence": "string"
}{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}Proposes the release payment; two of the three owners must sign to execute it.
| id required | string |
| ownerAddress | string Acting owner for the release/refund proposal (defaults to the sole on-chain owner). |
{- "ownerAddress": "string"
}{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}Proposes the refund payment; two of the three owners must sign to execute it.
| id required | string |
| ownerAddress | string Acting owner for the release/refund proposal (defaults to the sole on-chain owner). |
{- "ownerAddress": "string"
}{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}| id required | string |
{- "invoiceId": "string",
- "payeeName": { },
- "description": { },
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "arbiterAddress": "string",
- "chainId": 0,
- "status": "DRAFT",
- "holdWalletId": { },
- "holdAddress": { },
- "releasePaymentId": { },
- "refundPaymentId": { },
- "expiresAt": { },
- "createdAt": "string"
}| id required | string |
{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}| id required | string |
{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}| id required | string |
{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}Direct payment to the payee; rides M-of-N if the source wallet is multi-owner.
| id required | string |
| sourceWalletId required | string The wallet to pay the bill from. |
| ownerAddress | string Acting owner for the payment (if the wallet is M-of-N). |
{- "sourceWalletId": "string",
- "ownerAddress": "string"
}{- "invoiceId": "string",
- "amountUsd": "string",
- "payerAddress": "string",
- "payeeAddress": "string",
- "payeeName": { },
- "description": { },
- "chainId": 0,
- "payerTenantId": { },
- "senderTenantId": { },
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "payerPaymentId": { },
- "sigExpiresAt": { },
- "createdAt": "string"
}{- "account": {
- "chainId": 84532,
- "chainName": "Base Sepolia",
- "testnet": true,
- "asset": {
- "symbol": "DUSD",
- "label": "Demo USD",
- "address": "0xDdE94493605c1e64D9D5EE48A9CDA3A86bb4FfC9",
- "decimals": 6
}, - "primary": "SMART_ACCOUNT",
- "accounts": [
- {
- "kind": "SMART_ACCOUNT",
- "address": { },
- "walletId": { },
- "status": "READY",
- "amountBaseUnits": { },
- "amountUsd": "250.000000"
}
], - "funding": "FAUCET",
- "partial": true,
- "observedAt": "2026-09-16T12:00:00.000Z"
}, - "netBalanceUsd": "string",
- "balancePartial": true,
- "wallets": [
- {
- "walletId": "string",
- "name": { },
- "address": { },
- "chainId": { },
- "status": "string",
- "balanceUsd": { }
}
], - "billsOwed": {
- "count": 0,
- "totalUsd": "string",
- "bills": [
- {
- "invoiceId": "string",
- "amountUsd": "string",
- "senderAddress": { },
- "verificationStatus": "UNVERIFIED",
- "payerDecision": "ACCEPTED",
- "createdAt": "string"
}
]
}, - "recentActivity": [
- {
- "id": "string",
- "status": "string",
- "amountUsd": "string",
- "asset": "string",
- "destination": "string",
- "createdAt": "string"
}
], - "agentSpend": [
- {
- "agentId": "string",
- "name": { },
- "active": true,
- "perTransactionUsd": { },
- "limits": [
- {
- "interval": "daily",
- "capUsd": "string",
- "spentUsd": "string",
- "remainingUsd": "string"
}
]
}
], - "generatedAt": "string"
}| kind | string Default: "OTHER" Enum: "INVOICE" "PAYMENT_REQUEST" "PURCHASE" "SERVICE" "MILESTONE" "TRANSFER" "OTHER" |
| sourceType | string Default: "API" Enum: "CHAT" "TEMPLATE" "EMAIL" "UPLOAD" "API" "OTHER" |
| title required | string |
| description | string |
| currency required | string ISO currency or supported asset code. |
| authorizedTotalMinor required | string Authorized total in integer minor units. |
required | Array of objects (AgreementPartyInput) |
{- "kind": "INVOICE",
- "sourceType": "CHAT",
- "title": "Boat sale to Mike",
- "description": "string",
- "currency": "USD",
- "authorizedTotalMinor": "8000000",
- "parties": [
- {
- "partyKey": "payer",
- "role": "PAYER",
- "displayName": "Mike Reynolds",
- "did": "string",
- "invitedEmail": "string"
}
]
}{- "id": "string",
- "publicReference": "string",
- "kind": "string",
- "sourceType": "string",
- "title": "string",
- "description": { },
- "currency": "string",
- "authorizedTotalMinor": "string",
- "lifecycleState": "string",
- "acceptanceState": "string",
- "fundingState": "string",
- "settlementState": "string",
- "disputeState": "string",
- "riskStatus": "string",
- "aggregateVersion": 0,
- "parties": [
- {
- "id": "string",
- "partyKey": "string",
- "role": "string",
- "displayName": "string",
- "verificationState": "string",
- "did": { },
- "partyTenantId": "string",
- "accepted": true
}
], - "latestPolicyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}, - "createdAt": "string",
- "updatedAt": "string"
}| limit required | string |
{- "agreements": [
- {
- "id": "string",
- "publicReference": "string",
- "kind": "string",
- "sourceType": "string",
- "title": "string",
- "description": { },
- "currency": "string",
- "authorizedTotalMinor": "string",
- "lifecycleState": "string",
- "acceptanceState": "string",
- "fundingState": "string",
- "settlementState": "string",
- "disputeState": "string",
- "riskStatus": "string",
- "aggregateVersion": 0,
- "parties": [
- {
- "id": "string",
- "partyKey": "string",
- "role": "string",
- "displayName": "string",
- "verificationState": "string",
- "did": { },
- "partyTenantId": "string",
- "accepted": true
}
], - "latestPolicyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}, - "createdAt": "string",
- "updatedAt": "string"
}
]
}| agreementId required | string |
{- "id": "string",
- "publicReference": "string",
- "kind": "string",
- "sourceType": "string",
- "title": "string",
- "description": { },
- "currency": "string",
- "authorizedTotalMinor": "string",
- "lifecycleState": "string",
- "acceptanceState": "string",
- "fundingState": "string",
- "settlementState": "string",
- "disputeState": "string",
- "riskStatus": "string",
- "aggregateVersion": 0,
- "parties": [
- {
- "id": "string",
- "partyKey": "string",
- "role": "string",
- "displayName": "string",
- "verificationState": "string",
- "did": { },
- "partyTenantId": "string",
- "accepted": true
}
], - "latestPolicyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}, - "createdAt": "string",
- "updatedAt": "string"
}| agreementId required | string |
| expectedVersion required | number Optimistic concurrency token (aggregateVersion). |
object or null Set a financing request (intent only — nothing is applied for or funded) or pass null to withdraw it and pay from a funded source. | |
| title | string |
| description | string |
| authorizedTotalMinor | string |
{- "expectedVersion": 0,
- "financingRequest": {
- "requestedMinor": "50000",
- "coverage": "PURCHASE_PRICE"
}, - "title": "string",
- "description": "string",
- "authorizedTotalMinor": "8000000"
}{- "id": "string",
- "publicReference": "string",
- "kind": "string",
- "sourceType": "string",
- "title": "string",
- "description": { },
- "currency": "string",
- "authorizedTotalMinor": "string",
- "lifecycleState": "string",
- "acceptanceState": "string",
- "fundingState": "string",
- "settlementState": "string",
- "disputeState": "string",
- "riskStatus": "string",
- "aggregateVersion": 0,
- "parties": [
- {
- "id": "string",
- "partyKey": "string",
- "role": "string",
- "displayName": "string",
- "verificationState": "string",
- "did": { },
- "partyTenantId": "string",
- "accepted": true
}
], - "latestPolicyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}, - "createdAt": "string",
- "updatedAt": "string"
}Percentages freeze to exact integer minor units; the compiled definition is content-addressed (canonicalHash) and stored as the next DRAFT policy version. Validation failures return structured issues and store nothing.
| agreementId required | string |
| authoredPolicy | object Authored policy document (safebank.agreement-policy/1.0 authored form). Deep validation happens in the deterministic compiler; failures return structured issues. |
object (TemplateInvocation) |
{- "authoredPolicy": { },
- "template": {
- "templateId": "deposit-balance",
- "deadline": "string",
- "inputs": { }
}
}{- "ok": true,
- "issues": [
- {
- "code": "string",
- "path": "string",
- "message": "string"
}
], - "policyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}
}| agreementId required | string |
{- "ok": true,
- "issues": [
- {
- "code": "string",
- "path": "string",
- "message": "string"
}
], - "canonicalHash": "string"
}Answers "what happens if this fact arrives / the deadline passes / a dispute opens" from the same deterministic evaluator that will govern real releases. Never moves state or money.
| agreementId required | string |
Array of objects (SimulateFactInput) | |
| at | string Evaluate as of this instant (ISO-8601 UTC). |
object (SimulateDisputeInput) |
{- "injectFacts": [
- {
- "requirementId": "balance-confirmed",
- "factType": "safebank.stage.confirmed.v1"
}
], - "at": "string",
- "openDispute": {
- "affectedStageIds": [
- "string"
]
}
}{- "before": { },
- "after": { }
}On-chain provider: escrow address, deal id, and ordered approve/fund calldata steps. Sandbox provider: a note pointing at simulate-funding. Chain events (not client claims) are the source of funding truth.
| agreementId required | string |
{- "provider": "onchain",
- "escrowAddress": "string",
- "dealId": "string",
- "tokenAddress": "string",
- "chainId": 0,
- "amountMinor": "string",
- "steps": [
- {
- "kind": "approve",
- "to": "string",
- "data": "string"
}
], - "note": "string"
}Available only with the mock protection provider (no escrow configured). Routes through the same funding accounting/FSM the on-chain indexer uses.
| agreementId required | string |
| amountMinor required | string Deposit amount in integer minor units. |
{- "amountMinor": "8000000"
}Creates the content-addressed AgreementVersion binding parties, money, and the exact policy hash. Parties accept THIS hash — later edits create a new version and re-open acceptance.
| agreementId required | string |
{- "id": "string",
- "version": 0,
- "docHash": "string",
- "doc": { }
}| agreementId required | string |
| partyKey required | string |
| did | string Permara DID to bind this party to. |
| reference | string The agreement publicReference — the shared-link capability a joining counterparty presents. Not needed for existing participants. |
{- "did": "string",
- "reference": "string"
}The caller echoes the docHash + policyHash they reviewed; a mismatch (e.g. a concurrent amendment) is refused, so blind acceptance is impossible.
| agreementId required | string |
| partyKey required | string |
| agreementHash required | string Echo of the reviewed agreement version docHash. |
| policyHash required | string Echo of the reviewed policy canonicalHash. |
{- "partyKey": "payee",
- "agreementHash": "string",
- "policyHash": "string"
}Hashes are server-derived from the stored agreement/policy versions — the wallet signs what Permara will verify, nothing looser.
| agreementId required | string |
| scope required | string Enum: "ACTIVATION" "RELEASE" |
| stageId | string Stage id (RELEASE scope only). |
| payer required | string The payer's registered member signer address. |
| nonce required | string Single-use uint256 nonce (decimal string). |
| expiresAt required | string Expiry (ISO-8601 UTC), max 90 days out. |
{- "scope": "ACTIVATION",
- "stageId": "string",
- "payer": "string",
- "nonce": "string",
- "expiresAt": "string"
}{- "typedData": { }
}ACTIVATION scope preauthorizes every PREAUTHORIZED_CONDITIONAL stage of the exact policy version; RELEASE scope approves one stage just-in-time. Replay-fenced by nonce and digest.
| agreementId required | string |
| scope required | string Enum: "ACTIVATION" "RELEASE" |
| stageId | string Stage id (RELEASE scope only). |
| payer required | string The payer's registered member signer address. |
| nonce required | string Single-use uint256 nonce (decimal string). |
| expiresAt required | string Expiry (ISO-8601 UTC), max 90 days out. |
| signature required | string EIP-712 signature over the server-derived message. |
{- "scope": "ACTIVATION",
- "stageId": "string",
- "payer": "string",
- "nonce": "string",
- "expiresAt": "string",
- "signature": "string"
}{- "id": "string",
- "scope": "string",
- "stageId": { },
- "status": "string",
- "agreementHash": "string",
- "policyHash": "string",
- "releaseManifestHash": "string",
- "canonicalPayloadHash": "string",
- "expiresAt": "string"
}Creates an observation + attestation and runs deterministic trust evaluation. An accepted fact never moves money — it only feeds the policy evaluator. Contradictory attestations pause the stage for review; arrival order never decides.
| agreementId required | string |
| requirementId required | string |
| confirmed required | boolean true = the condition happened; false = it did not. |
| note | string |
{- "requirementId": "completion-confirmed",
- "confirmed": true,
- "note": "string"
}{- "observationId": "string",
- "attestationId": "string"
}Dependent accepted facts flip to REVOKED and the agreement re-evaluates — a stage that lost its proof returns to waiting.
| agreementId required | string |
| attestationId required | string |
| reason required | string |
{- "reason": "entered by mistake"
}What the conversation renders as the "Do not pay unless —" card, the rules card and the quorum stamps. Read-only; the decision itself stays with decisions/latest.
| agreementId required | string |
{- "draft": {
- "agreementId": "string",
- "templateId": "string",
- "documentRef": "string",
- "conditions": [
- {
- "sentence": "Completion is confirmed by both sides",
- "detail": "You and Harbor Goods each confirm — evidence optional",
- "state": "true"
}
], - "approvals": {
- "required": 0,
- "of": 0,
- "names": [
- "string"
]
}, - "rules": {
- "recipient": "string",
- "amount": "string",
- "paysWhen": "string",
- "approvals": "string"
}
}, - "state": {
- "agreementId": "string",
- "status": "DRAFT",
- "approvals": {
- "done": 0,
- "of": 0,
- "waitingOn": [
- "string"
], - "lastBy": "string",
- "at": "string"
}
}
}| agreementId required | string |
{- "id": "string",
- "decisionHash": "string",
- "inputSnapshotHash": "string",
- "evaluatedAt": "string",
- "result": { }
}A dispute can never claw back settled value; it only pauses stages that have not paid out. Resolution is mutual (the counterparty decides), and a resolved dispute never auto-releases: conditions still govern.
| agreementId required | string |
| reasonCode required | string |
| narrative | string |
| affectedStageIds | Array of strings Stage ids to freeze; omit for all unreleased stages. |
{- "reasonCode": "ITEM_NOT_AS_DESCRIBED",
- "narrative": "string",
- "affectedStageIds": [
- "string"
]
}{- "id": "string",
- "state": "string",
- "reasonCode": "string",
- "openedByPartyKey": "string",
- "openedAt": "string"
}| agreementId required | string |
| disputeId required | string |
| resolution required | string Enum: "RELEASE" "REFUND" |
| note | string |
{- "resolution": "RELEASE",
- "note": "string"
}Generated deterministically from the same structured policy the parties accept (never AI prose), with openQuestions driving the guided/chat creation flow. All clients render this one JSON contract.
| agreementId required | string |
A role-aware projection of the append-only event log, plus per-step unsatisfied conditions derived from the latest deterministic decision — exact reasons, never guesses.
| agreementId required | string |
{- "entries": [
- {
- "at": "string",
- "kind": "string",
- "label": "string"
}
], - "whyWaiting": [
- {
- "stageId": "string",
- "label": "string",
- "state": "string",
- "reasons": [
- "string"
]
}
]
}Content-addressed record of what was agreed (hashes), proven (fact/attestation hashes), authorized (EIP-712 digests), and settled — without private routing internals. Generated once on first request after completion.
| agreementId required | string |
Freezes the policy ACTIVE and spawns the runtime release rows and timeout timers. Releases stay withheld until funding covers them — activation never moves money.
| agreementId required | string |
{- "id": "string",
- "publicReference": "string",
- "kind": "string",
- "sourceType": "string",
- "title": "string",
- "description": { },
- "currency": "string",
- "authorizedTotalMinor": "string",
- "lifecycleState": "string",
- "acceptanceState": "string",
- "fundingState": "string",
- "settlementState": "string",
- "disputeState": "string",
- "riskStatus": "string",
- "aggregateVersion": 0,
- "parties": [
- {
- "id": "string",
- "partyKey": "string",
- "role": "string",
- "displayName": "string",
- "verificationState": "string",
- "did": { },
- "partyTenantId": "string",
- "accepted": true
}
], - "latestPolicyVersion": {
- "id": "string",
- "version": 0,
- "status": "string",
- "canonicalHash": "string",
- "definition": { }
}, - "createdAt": "string",
- "updatedAt": "string"
}| agreementId required | string |
| name required | string |
| requirementId required | string The proof requirement this source attests (from the policy). |
{- "name": "Title registry webhook",
- "requirementId": "title-transferred"
}{- "id": "string",
- "endpointId": "string",
- "name": "string",
- "requirementId": "string",
- "status": "string",
- "secret": "string",
- "ingestPath": "string"
}| agreementId required | string |
{- "sources": [
- {
- "id": "string",
- "endpointId": "string",
- "name": "string",
- "requirementId": "string",
- "status": "string",
- "createdAt": "string"
}
]
}| agreementId required | string |
| sourceId required | string |
{- "method": "string",
- "path": "string",
- "headers": { },
- "body": "string"
}Body: {"nonce": "<unique, 8..64 chars>", "confirmed": true|false, "note"?: string}. Creates an Observation/Attestation for the registered proof requirement — the deterministic policy engine decides everything after that.
| endpointId required | string |
{- "observationId": "string",
- "attestationId": "string"
}The first page carries every pinned conversation, then the newest unpinned ones; before pages the unpinned segment only.
| limit | string 1..100, default 50. |
| before | string ISO timestamp from a previous page's nextBefore. Pages the unpinned segment; pinned conversations all ride the first page. |
| pinned | boolean true = pinned conversations only; false = unpinned only. |
| kind | string Enum: "pay" "agreement" "invoice" "financing" "general" Only conversations of this kind. |
| attention | string Enum: "SIGNATURE" "CLARIFICATION" "REVIEW" "OFFER" Only conversations waiting on the person for this reason. |
| mine | boolean true = only the conversations this member opened. An API key has no member, so it receives no conversations. |
{- "sessions": [
- {
- "sessionId": "string",
- "title": { },
- "kind": "pay",
- "agreementId": { },
- "paymentId": { },
- "extractionId": { },
- "pinnedAt": { },
- "lastActivityAt": "string",
- "lastReply": { },
- "attention": "SIGNATURE",
- "createdAt": "string"
}
], - "nextBefore": { }
}| text | string The person's first words. When present the first turn runs at once and the response returns before it finishes — open the session and stream events from cursor 0. |
| attachments | Array of strings Upload ids attached to the first message (see POST /v1/payables/uploads). |
| clientTurnId | string Idempotency id for the first turn (default "first"). |
{- "text": "pay @harborgoods 250 for the rope order",
- "attachments": [
- "string"
], - "clientTurnId": "string"
}{- "sessionId": "string",
- "title": { },
- "kind": "pay",
- "agreementId": { },
- "paymentId": { },
- "extractionId": { },
- "pinnedAt": { },
- "lastActivityAt": "string",
- "lastReply": { },
- "attention": "SIGNATURE",
- "createdAt": "string",
- "provider": "anthropic",
- "model": "string",
- "promptVersion": "string"
}| sessionId required | string |
| title | string A new title for the conversation (1..80 characters). |
| pinned | boolean Pin (true) or unpin (false) on the Home list. |
{- "title": "string",
- "pinned": true
}{- "sessionId": "string",
- "title": { },
- "kind": "pay",
- "agreementId": { },
- "paymentId": { },
- "extractionId": { },
- "pinnedAt": { },
- "lastActivityAt": "string",
- "lastReply": { },
- "attention": "SIGNATURE",
- "createdAt": "string"
}| sessionId required | string |
{- "sessionId": "string",
- "title": { },
- "kind": "pay",
- "agreementId": { },
- "paymentId": { },
- "extractionId": { },
- "pinnedAt": { },
- "lastActivityAt": "string",
- "lastReply": { },
- "attention": "SIGNATURE",
- "createdAt": "string",
- "provider": "anthropic",
- "model": "string",
- "promptVersion": "string",
- "messages": [
- {
- "seq": 0,
- "role": "user",
- "text": "string",
- "toolCalls": [
- "string"
]
}
]
}| sessionId required | string |
| paymentId required | string The corridor payment the person signed from this conversation (POST /v1/offramp/payments). Must belong to the caller. |
{- "paymentId": "string"
}{- "sessionId": "string",
- "title": { },
- "kind": "pay",
- "agreementId": { },
- "paymentId": { },
- "extractionId": { },
- "pinnedAt": { },
- "lastActivityAt": "string",
- "lastReply": { },
- "attention": "SIGNATURE",
- "createdAt": "string"
}| sessionId required | string |
| text required | string The user message. Quoted documents are treated as data, never instructions. |
| mode | string Enum: "execute" "plan" plan = read tools run, write tools are returned as proposals with zero side effects. |
| clientTurnId | string Client-chosen idempotency id (unique per session). A replay returns the stored result; the same id with different content is a 409. |
| hostConfirmations | Array of strings Tool names the HOST confirmed with the user for this turn (e.g. send_for_review). Host-required tools refuse without it; model output can never supply it. |
| attachments | Array of strings Upload ids (POST /v1/payables/uploads) attached to this message. Verified to belong to the caller before the assistant sees them; the assistant reads them with prepare_document — bytes never enter the model context. |
{- "text": "I'm selling my boat to Mike Reynolds for $80,000 — $10,000 deposit when we sign.",
- "mode": "execute",
- "clientTurnId": "string",
- "hostConfirmations": [
- "string"
], - "attachments": [
- "string"
]
}{- "sessionId": "string",
- "resultId": "string",
- "correlationId": "string",
- "mode": "execute",
- "replayed": true,
- "reply": "string",
- "actions": [
- {
- "tool": "string",
- "ok": true,
- "summary": "string",
- "resultId": "string",
- "proposed": true,
- "reasonCodes": [
- "string"
]
}
], - "agreementId": { },
- "card": { },
- "clarifications": [
- { }
], - "reviewUrl": { },
- "providerMeta": {
- "provider": "string",
- "model": "string",
- "responseId": { },
- "reportedRevision": { }
}, - "limits": {
- "toolCalls": 0,
- "elapsedMs": 0,
- "exceeded": { }
}
}| sessionId required | string |
| cursor | string Last seq already seen (default 0). |
[- {
- "seq": 0,
- "type": "turn_started",
- "sessionId": "string",
- "correlationId": "string",
- "clientTurnId": "string",
- "at": "string",
- "objectRefs": [
- { }
], - "payload": { }
}
]| sessionId required | string |
| clientTurnId required | string |
{- "status": "cancel_requested",
- "note": "string"
}Runs the exact ingestion pipeline (scan → OCR → extraction → risk flags) without SES. Production requires PAYABLES_INGEST_SIMULATE=true.
| from required | string |
| subject | string |
| text | string Plain-text body. |
Array of objects (SimulatedAttachmentInput) |
{- "from": "Acme Marine <billing@acmemarine.example>",
- "subject": "Invoice 2041 — slip rental",
- "text": "string",
- "attachments": [
- {
- "filename": "invoice.txt",
- "contentType": "text/plain",
- "base64": "string"
}
]
}{- "messageId": "string",
- "status": "string",
- "extractionId": { }
}Organization-scoped. Runs the same pipeline as inbound mail (scan → OCR → extraction → risk flags). Returns an uploadId the assistant can read with prepare_document; bytes are never exposed back.
| filename required | string |
| contentType required | string Enum: "application/pdf" "image/png" "image/jpeg" "text/plain" "text/csv" |
| base64 required | string Base64 file bytes (max ~1MB). Bytes never transit a URL or a shell. |
{- "filename": "invoice-2041.pdf",
- "contentType": "application/pdf",
- "base64": "string"
}{- "uploadId": "string",
- "status": "EXTRACTED",
- "extractionId": "string",
- "sha256": "string"
}{- "extractions": [
- {
- "extraction": {
- "id": "string",
- "extractionId": "string",
- "uploadId": "string",
- "status": "EXTRACTED",
- "provider": "mock",
- "kind": "INVOICE",
- "title": "INV-2291 · ABC Construction · $18,500",
- "facts": [
- {
- "key": "string",
- "label": "string",
- "value": "string",
- "display": "$18,500 Demo USD",
- "confidence": 0,
- "note": "string",
- "source": "read"
}
], - "counterparty": {
- "name": "string",
- "verified": true
}, - "mismatches": [
- {
- "field": "string",
- "document": "string",
- "draft": "string"
}
], - "fieldsJson": { },
- "agreementId": "string",
- "duplicateOfId": "string",
- "createdAt": "string"
}, - "flags": [
- {
- "id": "string",
- "kind": "LOW_CONFIDENCE",
- "status": "OPEN",
- "field": "string",
- "detail": "string",
- "detailsJson": { }
}
]
}
]
}| extractionId required | string |
{- "extraction": {
- "id": "string",
- "extractionId": "string",
- "uploadId": "string",
- "status": "EXTRACTED",
- "provider": "mock",
- "kind": "INVOICE",
- "title": "INV-2291 · ABC Construction · $18,500",
- "facts": [
- {
- "key": "string",
- "label": "string",
- "value": "string",
- "display": "$18,500 Demo USD",
- "confidence": 0,
- "note": "string",
- "source": "read"
}
], - "counterparty": {
- "name": "string",
- "verified": true
}, - "mismatches": [
- {
- "field": "string",
- "document": "string",
- "draft": "string"
}
], - "fieldsJson": { },
- "agreementId": "string",
- "duplicateOfId": "string",
- "createdAt": "string"
}, - "flags": [
- {
- "id": "string",
- "kind": "LOW_CONFIDENCE",
- "status": "OPEN",
- "field": "string",
- "detail": "string",
- "detailsJson": { }
}
]
}| extractionId required | string |
| field required | string Enum: "vendorName" "vendorEmail" "invoiceNumber" "currency" "totalMinor" "dueDate" "bankDetails" "poNumber" "paymentTerms" "issueDate" "subtotalMinor" "taxMinor" "buyerName" |
| value required | string |
{- "field": "vendorName",
- "value": "string"
}{- "extraction": {
- "id": "string",
- "extractionId": "string",
- "uploadId": "string",
- "status": "EXTRACTED",
- "provider": "mock",
- "kind": "INVOICE",
- "title": "INV-2291 · ABC Construction · $18,500",
- "facts": [
- {
- "key": "string",
- "label": "string",
- "value": "string",
- "display": "$18,500 Demo USD",
- "confidence": 0,
- "note": "string",
- "source": "read"
}
], - "counterparty": {
- "name": "string",
- "verified": true
}, - "mismatches": [
- {
- "field": "string",
- "document": "string",
- "draft": "string"
}
], - "fieldsJson": { },
- "agreementId": "string",
- "duplicateOfId": "string",
- "createdAt": "string"
}, - "flags": [
- {
- "id": "string",
- "kind": "LOW_CONFIDENCE",
- "status": "OPEN",
- "field": "string",
- "detail": "string",
- "detailsJson": { }
}
]
}Blocked while risk flags are OPEN or critical fields are missing.
| extractionId required | string |
{- "agreementId": "string"
}| name required | string |
| subscriptionSeconds | number Subscription window length in seconds (default 7 days). |
| originationSeconds | number Origination window length in seconds after subscription close (default 30 days). |
{- "name": "Demo PO Pool A",
- "subscriptionSeconds": 604800,
- "originationSeconds": 2592000
}{- "id": "string",
- "name": "string",
- "chainId": 0,
- "provider": "string",
- "poolAddress": "string",
- "tokenAddress": "string",
- "registryAddress": "string",
- "phase": "string",
- "outcome": "string",
- "subscriptionOpenAt": "string",
- "subscriptionCloseAt": "string",
- "originationEndAt": "string",
- "minimumRaise": "string",
- "subscriptionCap": "string",
- "perLoanCap": "string",
- "absoluteExposureCap": "string",
- "exposureBps": 0,
- "reserveBps": 0,
- "annualRateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "state": {
- "totalUnits": "string",
- "frozenTotalUnits": "string",
- "openingCapital": "string",
- "accountedCash": "string",
- "principalCash": "string",
- "realizedInterestCash": "string",
- "performingPrincipal": "string",
- "defaultedPrincipal": "string",
- "cumulativePrincipalOriginated": "string",
- "cumulativePrincipalReceived": "string",
- "cumulativePrincipalWrittenDown": "string",
- "cumulativePrincipalRecovered": "string",
- "cumulativeDistributable": "string",
- "availableForNewLoans": "string"
}, - "environmentNotice": "string"
}{- "pools": [
- {
- "id": "string",
- "name": "string",
- "chainId": 0,
- "provider": "string",
- "poolAddress": "string",
- "tokenAddress": "string",
- "registryAddress": "string",
- "phase": "string",
- "outcome": "string",
- "subscriptionOpenAt": "string",
- "subscriptionCloseAt": "string",
- "originationEndAt": "string",
- "minimumRaise": "string",
- "subscriptionCap": "string",
- "perLoanCap": "string",
- "absoluteExposureCap": "string",
- "exposureBps": 0,
- "reserveBps": 0,
- "annualRateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "state": {
- "totalUnits": "string",
- "frozenTotalUnits": "string",
- "openingCapital": "string",
- "accountedCash": "string",
- "principalCash": "string",
- "realizedInterestCash": "string",
- "performingPrincipal": "string",
- "defaultedPrincipal": "string",
- "cumulativePrincipalOriginated": "string",
- "cumulativePrincipalReceived": "string",
- "cumulativePrincipalWrittenDown": "string",
- "cumulativePrincipalRecovered": "string",
- "cumulativeDistributable": "string",
- "availableForNewLoans": "string"
}, - "environmentNotice": "string"
}
]
}| poolId required | string |
{- "id": "string",
- "name": "string",
- "chainId": 0,
- "provider": "string",
- "poolAddress": "string",
- "tokenAddress": "string",
- "registryAddress": "string",
- "phase": "string",
- "outcome": "string",
- "subscriptionOpenAt": "string",
- "subscriptionCloseAt": "string",
- "originationEndAt": "string",
- "minimumRaise": "string",
- "subscriptionCap": "string",
- "perLoanCap": "string",
- "absoluteExposureCap": "string",
- "exposureBps": 0,
- "reserveBps": 0,
- "annualRateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "state": {
- "totalUnits": "string",
- "frozenTotalUnits": "string",
- "openingCapital": "string",
- "accountedCash": "string",
- "principalCash": "string",
- "realizedInterestCash": "string",
- "performingPrincipal": "string",
- "defaultedPrincipal": "string",
- "cumulativePrincipalOriginated": "string",
- "cumulativePrincipalReceived": "string",
- "cumulativePrincipalWrittenDown": "string",
- "cumulativePrincipalRecovered": "string",
- "cumulativeDistributable": "string",
- "availableForNewLoans": "string"
}, - "environmentNotice": "string"
}| poolId required | string |
{- "poolId": "string",
- "ownerAddress": "string",
- "units": "string",
- "deposited": "string",
- "withdrawn": "string",
- "claimed": "string",
- "claimable": "string",
- "phase": "string"
}Test funds only. Contributions become locked when subscriptions close; repayment is not guaranteed.
| poolId required | string |
| amount required | string Six-decimal integer atoms. |
{- "amount": "60000000000"
}{- "txRef": "string"
}| poolId required | string |
| amount required | string Six-decimal integer atoms. |
{- "amount": "60000000000"
}{- "txRef": "string"
}| poolId required | string Pool whose shared registry records the PO. |
| tradeOrderId | string A mutually signed Verified Sales Order (ADR 0028) — the preferred intake. The financing lock keys to its salesOrderHash; seller wallet, borrower and face amount derive from the order, and the pool-domain supplier acceptance is signed automatically (the commercial consent already exists in the SO). |
| extractionId | string Legacy intake: an APPROVED payables extraction id. |
| supplierTenantId | string Supplier tenant slug/id — the supplier's demo wallet is derived from it. Exactly one of supplierTenantId or supplierWallet is required. |
| supplierWallet | string Explicit supplier payout wallet. |
| faceAmount | string PO face amount in atoms; defaults to the extracted invoice amount. |
{- "poolId": "string",
- "tradeOrderId": "string",
- "extractionId": "string",
- "supplierTenantId": "string",
- "supplierWallet": "string",
- "faceAmount": "20000000000"
}{- "id": "string",
- "poId": "string",
- "extractionId": "string",
- "tradeOrderId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "faceAmount": "string",
- "status": "string"
}{- "purchaseOrders": [
- {
- "id": "string",
- "poId": "string",
- "extractionId": "string",
- "tradeOrderId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "faceAmount": "string",
- "status": "string"
}
]
}| id required | string |
| minPrincipal | string Supplier floor on financed principal (atoms); defaults to the PO face amount. |
{- "minPrincipal": "20000000000"
}{- "id": "string",
- "poId": "string",
- "extractionId": "string",
- "tradeOrderId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "faceAmount": "string",
- "status": "string"
}Issuer-attested MVP: the platform signs an EIP-712 eligibility permit over EXPLICIT synthetic evidence. The pool verifies the signature on-chain; a credential alone never moves funds.
| poolId required | string Pool the permit is domain-bound to (EIP-712 anti-replay). |
| mode required | string Enum: "synthetic" "plaid_sandbox" Evidence mode, named explicitly. synthetic = deterministic demo data; plaid_sandbox = a real token-exchange pipeline against the Plaid sandbox (503 when PLAID_CLIENT_ID/PLAID_SECRET are unset). Neither is ever a silent fallback for the other. |
| riskTier | number Synthetic risk tier 1 (best) – 5. |
{- "poolId": "string",
- "mode": "synthetic",
- "riskTier": 2
}{- "id": "string",
- "subjectAddress": "string",
- "schema": "string",
- "mode": "synthetic",
- "maxPrincipal": "string",
- "riskTier": 0,
- "profile": { },
- "permitDigest": "string",
- "issuerAddress": "string",
- "expiresAt": "string",
- "status": "string"
}[- {
- "id": "string",
- "subjectAddress": "string",
- "schema": "string",
- "mode": "synthetic",
- "maxPrincipal": "string",
- "riskTier": 0,
- "profile": { },
- "permitDigest": "string",
- "issuerAddress": "string",
- "expiresAt": "string",
- "status": "string"
}
]| poolId required | string |
| poId required | string Canonical registered PO id (0x…32 bytes). |
| principal required | string Requested principal in atoms. |
{- "poolId": "string",
- "poId": "string",
- "principal": "20000000000"
}{- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "principal": "string",
- "rateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "deadline": "string",
- "offerDigest": "string",
- "status": "string"
}| id required | string |
{- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "principal": "string",
- "rateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "deadline": "string",
- "offerDigest": "string",
- "status": "string"
}{- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "principal": "string",
- "rateBps": 0,
- "tenorSeconds": 0,
- "graceSeconds": 0,
- "deadline": "string",
- "offerDigest": "string",
- "status": "string"
}| offerId required | string An ACCEPTED lending offer id. |
{- "offerId": "string"
}{- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "principal": "string",
- "principalOutstanding": "string",
- "interestDue": "string",
- "status": "string",
- "fundedAt": "string",
- "maturityAt": "string",
- "graceEndsAt": "string"
}{- "loans": [
- {
- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "principal": "string",
- "principalOutstanding": "string",
- "interestDue": "string",
- "status": "string",
- "fundedAt": "string",
- "maturityAt": "string",
- "graceEndsAt": "string"
}
]
}| id required | string |
{- "id": "string",
- "poolId": "string",
- "poId": "string",
- "borrowerAddress": "string",
- "supplierWallet": "string",
- "principal": "string",
- "principalOutstanding": "string",
- "interestDue": "string",
- "status": "string",
- "fundedAt": "string",
- "maturityAt": "string",
- "graceEndsAt": "string"
}Available during pauses, delinquency, default, and after closure — a post-default payment is a recovery for the same frozen cohort. Third-party payers gain nothing.
| id required | string |
| maxAmount required | string Maximum the payer authorizes (atoms). |
| deadlineSeconds | number Authorization validity in seconds (default 3600). |
{- "maxAmount": "20197260273",
- "deadlineSeconds": 3600
}{- "txRef": "string",
- "amount": "string",
- "interestPortion": "string",
- "principalPortion": "string",
- "loanStatus": "string"
}| sellerTenantId required | string Seller tenant id — resolves the seller DID and demo wallet. |
| extractionId | string Seed the draft terms from an APPROVED payables extraction (uploaded PO). |
| agreementId | string Seed the draft from an agreement's financing request (ADR 0026 §5): total = requestedMinor, seller must match the beneficiary party's tenant. Financing the resulting sales order fulfills the agreement's request. |
object (TradeTermsInput) |
{- "sellerTenantId": "string",
- "extractionId": "string",
- "agreementId": "string",
- "terms": {
- "lineItems": [
- {
- "description": "Marine diesel engines",
- "amountAtoms": "20000000000"
}
], - "dueDays": 14,
- "deliveryTerms": "FOB destination, 2 crates"
}
}{- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}{- "orders": [
- {
- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}
]
}{- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}| id required | string |
required | object (TradeTermsInput) | ||||||
| |||||||
{- "terms": {
- "lineItems": [
- {
- "description": "Marine diesel engines",
- "amountAtoms": "20000000000"
}
], - "dueDays": 14,
- "deliveryTerms": "FOB destination, 2 crates"
}
}{- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}| id required | string |
{- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}| id required | string |
| action required | string Enum: "accept" "request-changes" "reject" |
| note | string Required note for request-changes. |
{- "action": "accept",
- "note": "string"
}{- "id": "string",
- "number": "string",
- "status": "string",
- "version": 0,
- "buyerTenantId": "string",
- "sellerTenantId": "string",
- "buyerDid": "string",
- "sellerDid": "string",
- "totalAtoms": "string",
- "currency": "string",
- "dueDays": 0,
- "terms": { },
- "contentHash": "string",
- "changeNote": "string",
- "buyerSigned": true,
- "sellerSigned": true,
- "salesOrderHash": "string",
- "agreementId": "string",
- "financeable": true
}| id required | string |
| note | string |
| evidenceUploadIds | Array of strings Payables upload ids attached as delivery evidence. |
{- "note": "Delivered to pier 4, signed by receiving manager.",
- "evidenceUploadIds": [
- "string"
]
}{- "id": "string",
- "orderId": "string",
- "status": "string",
- "note": "string",
- "evidenceHash": "string",
- "deliveredAt": "string",
- "acceptedAt": "string",
- "invoiceId": "string"
}| id required | string |
[- {
- "id": "string",
- "orderId": "string",
- "status": "string",
- "note": "string",
- "evidenceHash": "string",
- "deliveredAt": "string",
- "acceptedAt": "string",
- "invoiceId": "string"
}
]| id required | string |
{- "id": "string",
- "orderId": "string",
- "status": "string",
- "note": "string",
- "evidenceHash": "string",
- "deliveredAt": "string",
- "acceptedAt": "string",
- "invoiceId": "string"
}Re-verifies the whole document chain — identities, mutual sales-order signatures against the exact content, delivery acceptance, invoice match — before any funds move.
| id required | string |
{- "id": "string",
- "invoiceId": "string",
- "route": "FINANCIER",
- "amountAtoms": "string",
- "interestPortion": "string",
- "principalPortion": "string",
- "sellerPortion": "string",
- "remainingFinancingCost": "string",
- "matchedChecks": { }
}