Skip to main content

Permara Infrastructure API (1.0.0)

Download OpenAPI specification:Download

Issuing, settlement, refunds, and on-ramp infrastructure for partner platforms.

cards

Issue a card

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.

Request Body schema: application/json
required
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 standard.

Responses

Request samples

Content type
application/json
{
  • "cardholderId": "550e8400-e29b-41d4-a716-446655440000",
  • "chain": "solana",
  • "cryptoAccountAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
  • "cryptoAccountType": "standard"
}

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "stripeCardId": "ic_1NXxxx",
  • "bridgeCardAccountId": "card_acc_abc123",
  • "last4": "4242"
}

Issue Stripe ephemeral key for wallet push-provisioning

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.

path Parameters
id
required
string
Example: 6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1

Permara card UUID

Request Body schema: application/json
required
platform
required
string
Enum: "apple" "google"

Target wallet vendor. apple requires Apple Pay In-App Provisioning fields.

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 nonce produced by PKAddPaymentPassRequest. Required when platform=apple AND nonce is set; omit with nonce for the desktop / dry-run ephemeral-key path.

certificates
Array of strings

Apple Pay only — array of base64 certificates from PKAddPaymentPassRequest. Required when platform=apple AND nonce is set.

Responses

Request samples

Content type
application/json
{
  • "platform": "apple",
  • "nonce": "string",
  • "nonceSignature": "string",
  • "certificates": [
    ]
}

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "stripeCardId": "ic_1NXxxx",
  • "platform": "apple",
  • "ephemeralKey": {
    }
}

Get card spend limits

The configured per-transaction / daily / weekly / monthly caps and MCC rules for a card.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Permara card UUID

Responses

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "perTransactionUsd": "250.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00",
  • "blockedMcc": [ ],
  • "allowedMcc": null
}

Set card spend limits

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Permara card UUID

Request Body schema: application/json
required
perTransactionUsd
object or null

Per-transaction USD cap. null clears it.

dailyUsd
object or null

Rolling 24h USD cap. null clears it.

weeklyUsd
object or null

Rolling ISO-week USD cap. null clears it.

monthlyUsd
object or null

Calendar-month USD cap. null clears it.

blockedMcc
Array of strings

MCCs to decline. Replaces the existing list.

allowedMcc
Array of strings or null

When set, only these MCCs are allowed. null clears the allowlist (allow anything not blocked).

Responses

Request samples

Content type
application/json
{
  • "perTransactionUsd": "250.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00",
  • "blockedMcc": [
    ],
  • "allowedMcc": [
    ]
}

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "perTransactionUsd": "250.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00",
  • "blockedMcc": [ ],
  • "allowedMcc": null
}

Freeze a card

Sets the card inactive at Stripe and in Permara — subsequent authorizations decline immediately.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Permara card UUID

Responses

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "status": "inactive",
  • "last4": "4242",
  • "safeAddress": "0x1111111111111111111111111111111111111111"
}

Unfreeze a card

Reactivates a frozen card.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Permara card UUID

Responses

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "status": "inactive",
  • "last4": "4242",
  • "safeAddress": "0x1111111111111111111111111111111111111111"
}

Issue a card from a wallet

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
walletId
required
string

Source wallet id (must be DEPLOYED).

Request Body schema: application/json
required
perTransactionUsd
object or null

Per-transaction USD cap. null clears it.

dailyUsd
object or null

Rolling 24h USD cap. null clears it.

weeklyUsd
object or null

Rolling ISO-week USD cap. null clears it.

monthlyUsd
object or null

Calendar-month USD cap. null clears it.

blockedMcc
Array of strings

MCCs to decline. Replaces the existing list.

allowedMcc
Array of strings or null

When set, only these MCCs are allowed. null clears the allowlist (allow anything not blocked).

agentId
string

Bind the card to an agent (its spend also accumulates under the agent).

Responses

Request samples

Content type
application/json
{
  • "perTransactionUsd": "250.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00",
  • "blockedMcc": [
    ],
  • "allowedMcc": [
    ],
  • "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890"
}

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "stripeCardId": "ic_1NXxxx",
  • "last4": "4242",
  • "safeAddress": "0x1111111111111111111111111111111111111111",
  • "status": "active"
}

offramp

Create a phone-addressed payment (routes quoted when eligible)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "phone": "+15551234567",
  • "did": "did:safebank:lance",
  • "amountUsd": "25.00",
  • "chainId": 0,
  • "fundingMode": "INTERNAL_BALANCE",
  • "refundAddress": "string",
  • "funding": {
    },
  • "envelope": {
    },
  • "memo": "string",
  • "requestedDestinationId": "string",
  • "speedPreference": "FASTEST",
  • "maximumFeeMinor": "300",
  • "allowedRails": [
    ],
  • "invite": {
    }
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    },
  • "quotes": [
    ]
}

List corridor payments (sent or received)

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "payments": [
    ]
}

Fetch one corridor payment

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    }
}

Current active route quotes

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "routes": [
    ],
  • "excludedRoutes": [
    ]
}

Select a route quote (recipient only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
routeQuoteId
required
string

Route quote id to select.

Responses

Request samples

Content type
application/json
{
  • "routeQuoteId": "string"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    }
}

Confirm the selected route — locks funds and starts execution (recipient only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    }
}

Cancel an unfunded payment (sender only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    }
}

Simulate the funding deposit (sandbox only, sender only) — refused in production

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
amountMinor
required
string

Deposit amount in integer minor units.

Responses

Request samples

Content type
application/json
{
  • "amountMinor": "8000000"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "recipientPhoneMasked": { },
  • "recipientDid": "string",
  • "envelopeId": "string",
  • "recipientTenantId": { },
  • "claimId": { },
  • "sourceChainKey": "string",
  • "sourceAssetId": "string",
  • "sourceAmountBaseUnits": "string",
  • "sourceFundingMode": "string",
  • "requestedDestinationId": { },
  • "selectedRouteQuoteId": { },
  • "holdReasons": [
    ],
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string",
  • "fundingInstructions": {
    },
  • "quotes": [
    ]
}

payments

Approval requests in the tenant, newest first

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "approvals": [
    ]
}

Vote on an approval request (members only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
decision
string
Default: "APPROVE"
Enum: "APPROVE" "REJECT"
signature
string

EIP-191 signature over the approval vote message (optional hardening).

Responses

Request samples

Content type
application/json
{
  • "decision": "APPROVE",
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "paymentId": "string",
  • "requiredWeight": 0,
  • "approvalGroup": { },
  • "status": "PENDING",
  • "receivedWeight": 0,
  • "signatures": [
    ],
  • "createdAt": "string"
}

Reject an approval request (any authorized rejection is final)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "paymentId": "string",
  • "requiredWeight": 0,
  • "approvalGroup": { },
  • "status": "PENDING",
  • "receivedWeight": 0,
  • "signatures": [
    ],
  • "createdAt": "string"
}

Create a payment (normalized intent, or the deprecated Safe-debit shape)

Normalized intents describe the payment (recipient/amount/funding/delivery) and let Permara route it. Legacy bodies (sourceWalletId + destination) continue to work with deprecation headers.

Authorizations:
apiKeyAuthprivyBearer
header Parameters
x-safebank-2fa-challenge
string
idempotency-key
required
string
Idempotency-Key
string
Request Body schema: application/json
required
One of
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).

Responses

Request samples

Content type
application/json
Example
{
  • "recipient": {
    },
  • "amount": {
    },
  • "funding": {
    },
  • "delivery": {
    },
  • "purpose": {
    },
  • "envelope": {
    },
  • "memo": "string",
  • "metadata": { },
  • "idempotencyKey": "string",
  • "requestedDestinationId": "string"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

List payments (legacy Safe-debit list by default; kind=unified for intents)

Authorizations:
apiKeyAuthprivyBearer
query Parameters
kind
string
Enum: "legacy" "unified"
skip
string
take
string

Responses

Response samples

Content type
application/json
{
  • "payments": [
    ],
  • "total": 0,
  • "skip": 0,
  • "take": 0
}

Fetch one payment (unified intents and legacy payments share ids)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

Current route quotes + why withheld routes were excluded

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "routes": [
    ],
  • "excludedRoutes": [
    ]
}

Select a route quote (recipient only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
routeQuoteId
required
string

Route quote id to select.

Responses

Request samples

Content type
application/json
{
  • "routeQuoteId": "string"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

Approve a held payment (votes the caller's member on its approval request)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

Confirm the selected route — locks funds, starts execution

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

Cancel (unified intents and legacy payments share ids)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
ownerAddress
string

Owner address to act as. Optional for single-owner wallets.

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "CREATED",
  • "internalStatus": "string",
  • "recipientKind": "string",
  • "recipientDisplay": { },
  • "envelopeId": { },
  • "recipientIdentityId": { },
  • "amountValue": "string",
  • "amountCurrency": "string",
  • "fundingAssetId": "string",
  • "fundingChainKey": "string",
  • "holdReasons": [
    ],
  • "approvalRequestId": { },
  • "selectedRouteQuoteId": { },
  • "purpose": { },
  • "metadata": { },
  • "failureReason": { },
  • "deliveredAt": { },
  • "createdAt": "string"
}

[legacy] Sign a Safe-debit payment

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
signature
required
string

Raw secp256k1 signature over the safeTxHash.

Responses

Request samples

Content type
application/json
{
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "sourceWalletId": "string",
  • "destinationType": "handle",
  • "destinationHandle": { },
  • "destinationAddress": "string",
  • "destinationChainId": 0,
  • "asset": "usdc",
  • "amount": "25.00",
  • "status": "CREATED",
  • "safeTxHash": { },
  • "executedTxHash": { },
  • "memo": { },
  • "failureReason": { },
  • "createdAt": "string"
}

[legacy] Execute a threshold-met Safe-debit payment

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
ownerAddress
string

Owner address to act as. Optional for single-owner wallets.

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "sourceWalletId": "string",
  • "destinationType": "handle",
  • "destinationHandle": { },
  • "destinationAddress": "string",
  • "destinationChainId": 0,
  • "asset": "usdc",
  • "amount": "25.00",
  • "status": "CREATED",
  • "safeTxHash": { },
  • "executedTxHash": { },
  • "memo": { },
  • "failureReason": { },
  • "createdAt": "string"
}

Quote a payment to a DID

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
object (Function)

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "quoteId": "string",
  • "payee": {
    },
  • "recipientSettlement": {
    },
  • "sender": {
    },
  • "recipient": {
    },
  • "fees": {
    },
  • "estimatedSettlementSeconds": 0,
  • "expiresAt": "string"
}

webhooks

Register a webhook endpoint (secret shown once)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
url
required
string
enabledEvents
required
Array of strings
description
string

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": "string",
  • "url": "string",
  • "enabledEvents": [
    ],
  • "status": "string",
  • "description": { },
  • "createdAt": "string",
  • "secret": "string"
}

List webhook endpoints

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "endpoints": [
    ]
}

Update an endpoint (status and/or subscribed events)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
status
string
Enum: "ACTIVE" "DISABLED"
enabledEvents
Array of strings

Responses

Request samples

Content type
application/json
{
  • "status": "ACTIVE",
  • "enabledEvents": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "url": "string",
  • "enabledEvents": [
    ],
  • "status": "string",
  • "description": { },
  • "createdAt": "string"
}

Disable an endpoint (deliveries stop; history kept)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "url": "string",
  • "enabledEvents": [
    ],
  • "status": "string",
  • "description": { },
  • "createdAt": "string"
}

Rotate the signing secret (new value shown once)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "url": "string",
  • "enabledEvents": [
    ],
  • "status": "string",
  • "description": { },
  • "createdAt": "string",
  • "secret": "string"
}

Emitted events, newest first

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "events": [
    ]
}

Delivery attempts (filter by endpoint_id)

Authorizations:
apiKeyAuthprivyBearer
query Parameters
endpoint_id
string

Responses

Response samples

Content type
application/json
{
  • "deliveries": [
    ]
}

Re-queue one delivery (same stable event id)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "eventId": "string",
  • "endpointId": "string",
  • "status": "string",
  • "attempts": 0,
  • "httpStatus": { },
  • "lastError": { },
  • "nextAttemptAt": "string",
  • "deliveredAt": { }
}

claims

Inspect a claim link (public; the token is the authorization)

path Parameters
claimToken
required
string

Responses

Response samples

Content type
application/json
{
  • "amountUsd": "25.00",
  • "assetId": "string",
  • "chainKey": "eip155:84532",
  • "status": "string",
  • "expiresAt": "string",
  • "phoneMasked": "+1 ••• 4567"
}

Send a 6-digit code to the claim's stored phone (public)

path Parameters
claimToken
required
string

Responses

Response samples

Content type
application/json
{
  • "challengeId": "string",
  • "expiresAt": "string"
}

Confirm the phone code (public; 5 attempts per challenge)

path Parameters
claimToken
required
string
Request Body schema: application/json
required
challengeId
required
string

Challenge id returned by verify-phone.

code
required
string

6-digit code from the SMS.

Responses

Request samples

Content type
application/json
{
  • "challengeId": "string",
  • "code": "123456"
}

Response samples

Content type
application/json
{
  • "challengeId": "string",
  • "verified": true
}

Redeem a claim into your tenant (verified phone challenge + active destination)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
claimToken
required
string
Request Body schema: application/json
required
challengeId
required
string

A VERIFIED phone challenge id for this claim.

destinationId
required
string

One of the caller tenant's ACTIVE payout destination ids.

Responses

Request samples

Content type
application/json
{
  • "challengeId": "string",
  • "destinationId": "string"
}

Response samples

Content type
application/json
{
  • "paymentId": "string",
  • "status": "string",
  • "holdReasons": [
    ],
  • "quotes": [
    ]
}

Re-send the claim SMS with a fresh link (sender only, budgeted)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
claimId
required
string

Responses

Response samples

Content type
application/json
{
  • "expiresAt": "string"
}

Request an expired-claim refund (sender only; pre-expiry returns 409; idempotent)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
claimId
required
string

Responses

Response samples

Content type
application/json
{
  • "claimStatus": "string",
  • "paymentStatus": "string",
  • "refundTxHash": { }
}

dids

Reserve an identity for someone not on Permara yet

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
email
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.

Responses

Request samples

Content type
application/json
{
  • "email": "ap@harborgoods.example",
  • "phone": "+14155550123"
}

Response samples

Content type
application/json
{
  • "did": "did:permara:7f5df4d16e3c8a2e4b1c9d0a3f6e8b7c2d5a4f1e9c8b7a6d5e4f3c2b1a0f9e8d",
  • "status": "PROVISIONED",
  • "subjectType": "TENANT",
  • "verifiedAt": "string",
  • "createdAt": "string",
  • "version": 0,
  • "registryStatus": "string",
  • "registryTxHash": "string",
  • "documentUri": "string"
}

The caller's payment identities

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "dids": [
    ]
}

Does this DID resolve to a payable identity?

Authorizations:
apiKeyAuthprivyBearer
query Parameters
did
required
string

Responses

Response samples

Content type
application/json
{
  • "did": "did:permara:7f5df4d16e3c8a2e4b1c9d0a3f6e8b7c2d5a4f1e9c8b7a6d5e4f3c2b1a0f9e8d",
  • "resolvable": true,
  • "displayName": "string"
}

Public DID document (no endpoints, no PII)

path Parameters
did
required
string

Responses

W3C DID Resolution result for a did:permara identifier

path Parameters
did
required
string

Responses

Response samples

Content type
application/json
{
  • "didResolutionMetadata": { },
  • "didDocument": { },
  • "didDocumentMetadata": { }
}

The caller's payment profile (identity + endpoints, masked)

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "tenantId": "string",
  • "dids": [
    ],
  • "credentials": [
    ],
  • "destinations": [
    ]
}

capabilities

Self-describing platform capabilities

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.

Responses

Response samples

Content type
application/json
{
  • "apiVersion": "1",
  • "environment": "sandbox",
  • "chains": [
    ],
  • "features": {
    }
}

tenants

Create (bootstrap) a tenant

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.

Authorizations:
privyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "name": "Acme Robotics",
  • "slug": "acme-robotics"
}

Response samples

Content type
application/json
{
  • "id": "b3f1c2a0-1111-2222-3333-444455556666",
  • "slug": "acme-robotics",
  • "name": "Acme Robotics",
  • "role": "OWNER",
  • "createdAt": "2026-08-09T12:00:00.000Z"
}

Get the current tenant

Returns the tenant the caller is acting as — resolved from the Privy session's membership or from the developer API key.

Authorizations:
privyBearer

Responses

Response samples

Content type
application/json
{
  • "id": "b3f1c2a0-1111-2222-3333-444455556666",
  • "slug": "acme-robotics",
  • "name": "Acme Robotics",
  • "role": "OWNER",
  • "createdAt": "2026-08-09T12:00:00.000Z"
}

members

Invite a member

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
email
required
string

Invitee email.

displayName
string

Display name for the member.

role
string
Default: "MEMBER"
Enum: "ADMIN" "MEMBER"

Responses

Request samples

Content type
application/json
{
  • "email": "bob@acme.com",
  • "displayName": "Bob Jones",
  • "role": "ADMIN"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "email": { },
  • "displayName": { },
  • "role": "MEMBER",
  • "status": "PENDING",
  • "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
  • "privyUserId": { },
  • "createdAt": "string",
  • "acceptedAt": { },
  • "inviteToken": "string"
}

List members

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "members": [
    ]
}

Revoke a member

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "status": "REVOKED",
  • "stillOwnerOfWalletIds": [ ]
}

Accept an invite

Token-authenticated (no API key needed). Activates the member and registers the EVM address they will sign with.

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "token": "string",
  • "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
  • "displayName": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "email": { },
  • "displayName": { },
  • "role": "MEMBER",
  • "status": "PENDING",
  • "signerAddress": "0x83172d9A819b7895cEE10F4B52bB4Ec40114D39C",
  • "privyUserId": { },
  • "createdAt": "string",
  • "acceptedAt": { }
}

A member's authority grants (all statuses)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
memberId
required
string

Responses

Response samples

Content type
application/json
{
  • "authorities": [
    ]
}

Grant authority — returns the attestation the org Safe should sign

Authorizations:
apiKeyAuthprivyBearer
path Parameters
memberId
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "allowedActions": [
    ],
  • "perTxLimitUsd": "string",
  • "dailyLimitUsd": "string",
  • "monthlyLimitUsd": "string",
  • "allowedCurrencies": [
    ],
  • "allowedAssets": [
    ],
  • "allowedChains": [
    ],
  • "allowedDestinationIds": [
    ],
  • "approvalGroup": "string",
  • "approvalWeight": 1,
  • "requiresCountersignature": true,
  • "countersignAboveUsd": "string",
  • "validUntil": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "memberId": "string",
  • "credentialId": { },
  • "allowedActions": [
    ],
  • "perTxLimitUsd": { },
  • "dailyLimitUsd": { },
  • "monthlyLimitUsd": { },
  • "allowedCurrencies": [
    ],
  • "allowedAssets": [
    ],
  • "allowedChains": [
    ],
  • "allowedDestinationIds": [
    ],
  • "approvalGroup": { },
  • "approvalWeight": 0,
  • "requiresCountersignature": true,
  • "countersignAboveUsd": { },
  • "status": "ACTIVE",
  • "validFrom": "string",
  • "validUntil": { },
  • "version": 0,
  • "attestation": {
    }
}

Suspend/reactivate or reschedule an authority

Authorizations:
apiKeyAuthprivyBearer
path Parameters
memberId
required
string
authorityId
required
string
Request Body schema: application/json
required
status
string
Enum: "ACTIVE" "SUSPENDED"
validUntil
object

ISO-8601 expiry; null clears it.

Responses

Request samples

Content type
application/json
{
  • "status": "ACTIVE",
  • "validUntil": { }
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "memberId": "string",
  • "credentialId": { },
  • "allowedActions": [
    ],
  • "perTxLimitUsd": { },
  • "dailyLimitUsd": { },
  • "monthlyLimitUsd": { },
  • "allowedCurrencies": [
    ],
  • "allowedAssets": [
    ],
  • "allowedChains": [
    ],
  • "allowedDestinationIds": [
    ],
  • "approvalGroup": { },
  • "approvalWeight": 0,
  • "requiresCountersignature": true,
  • "countersignAboveUsd": { },
  • "status": "ACTIVE",
  • "validFrom": "string",
  • "validUntil": { },
  • "version": 0
}

Revoke an authority and its backing credential atomically

Authorizations:
apiKeyAuthprivyBearer
path Parameters
memberId
required
string
authorityId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "memberId": "string",
  • "credentialId": { },
  • "allowedActions": [
    ],
  • "perTxLimitUsd": { },
  • "dailyLimitUsd": { },
  • "monthlyLimitUsd": { },
  • "allowedCurrencies": [
    ],
  • "allowedAssets": [
    ],
  • "allowedChains": [
    ],
  • "allowedDestinationIds": [
    ],
  • "approvalGroup": { },
  • "approvalWeight": 0,
  • "requiresCountersignature": true,
  • "countersignAboveUsd": { },
  • "status": "ACTIVE",
  • "validFrom": "string",
  • "validUntil": { },
  • "version": 0
}

Attach the org-Safe EIP-1271 attestation (issues the AUTHORITY_DELEGATION credential)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
memberId
required
string
authorityId
required
string
Request Body schema: application/json
required
signature
required
string

Safe signature blob over the attestation hash (EIP-1271).

Responses

Request samples

Content type
application/json
{
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "memberId": "string",
  • "credentialId": { },
  • "allowedActions": [
    ],
  • "perTxLimitUsd": { },
  • "dailyLimitUsd": { },
  • "monthlyLimitUsd": { },
  • "allowedCurrencies": [
    ],
  • "allowedAssets": [
    ],
  • "allowedChains": [
    ],
  • "allowedDestinationIds": [
    ],
  • "approvalGroup": { },
  • "approvalWeight": 0,
  • "requiresCountersignature": true,
  • "countersignAboveUsd": { },
  • "status": "ACTIVE",
  • "validFrom": "string",
  • "validUntil": { },
  • "version": 0
}

keys

Create an API key

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).

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
name
required
string

Human label for the key.

environment
string
Enum: "test" "live"

Environment. Defaults to test.

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 * for a root key. Agent keys (created via the agents API) cannot hold agents:manage / keys:manage / policies:write.

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).

Responses

Request samples

Content type
application/json
{
  • "name": "CI sandbox",
  • "environment": "test",
  • "scopes": [
    ],
  • "expiresAt": "2027-01-01T00:00:00.000Z",
  • "rateLimitPerMinute": 1,
  • "ipAllowlist": [
    ],
  • "actingMemberId": "string"
}

Response samples

Content type
application/json
{
  • "id": "c1a2b3d4-...",
  • "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  • "pubId": "Ab12Cd34Ef56",
  • "environment": "TEST",
  • "scopes": [
    ],
  • "expiresAt": null,
  • "createdAt": "2026-08-09T12:00:00.000Z"
}

List API keys

Metadata only — never the secret.

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "keys": [
    ]
}

Revoke an API key

Soft-revokes the key (the row is kept for audit). Idempotent.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

API key id.

Responses

Rotate an API key

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

API key id to rotate.

Responses

Response samples

Content type
application/json
{
  • "id": "c1a2b3d4-...",
  • "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  • "pubId": "Ab12Cd34Ef56",
  • "environment": "TEST",
  • "scopes": [
    ],
  • "expiresAt": null,
  • "createdAt": "2026-08-09T12:00:00.000Z"
}

Set up (or rotate) request signing for a key

Generates the HMAC signing secret — shown ONCE — and, when required is true, makes every @HighRiskOperation route demand a signed request from this key.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
required
boolean
Default: true

Require signatures on @HighRiskOperation routes (default true).

Responses

Request samples

Content type
application/json
{
  • "required": true
}

Response samples

Content type
application/json
{
  • "keyId": "string",
  • "signingSecret": "string",
  • "signingRequired": true
}

agents

Create an agent

Creates a tenant-owned agent principal.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
name
required
string

Human label for the agent.

Responses

Request samples

Content type
application/json
{
  • "name": "ap-bot"
}

Response samples

Content type
application/json
{
  • "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "name": "ap-bot",
  • "status": "ACTIVE",
  • "createdAt": "2026-08-10T00:00:00.000Z"
}

List agents

Tenant-scoped, newest first.

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "agents": [
    ]
}

Get an agent

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Responses

Response samples

Content type
application/json
{
  • "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "name": "ap-bot",
  • "status": "ACTIVE",
  • "createdAt": "2026-08-10T00:00:00.000Z"
}

Suspend an agent

A suspended agent is declined (AGENT_SUSPENDED) on its next action.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Responses

Response samples

Content type
application/json
{
  • "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "name": "ap-bot",
  • "status": "ACTIVE",
  • "createdAt": "2026-08-10T00:00:00.000Z"
}

Reactivate a suspended agent

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Responses

Response samples

Content type
application/json
{
  • "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "name": "ap-bot",
  • "status": "ACTIVE",
  • "createdAt": "2026-08-10T00:00:00.000Z"
}

Get an agent’s spend limits

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Responses

Response samples

Content type
application/json
{
  • "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "perTransactionUsd": "50.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00"
}

Set an agent’s spend limits

Per-payment / daily / weekly / monthly USD caps enforced on every agent-initiated payment. Only the fields sent change; an explicit null clears a cap.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Request Body schema: application/json
required
perTransactionUsd
object or null

Per-payment USD cap. null clears it.

dailyUsd
object or null

Rolling 24h USD cap. null clears it.

weeklyUsd
object or null

Rolling ISO-week USD cap. null clears it.

monthlyUsd
object or null

Calendar-month USD cap. null clears it.

Responses

Request samples

Content type
application/json
{
  • "perTransactionUsd": "50.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00"
}

Response samples

Content type
application/json
{
  • "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "perTransactionUsd": "50.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00"
}

Mint an agent-scoped API key

Returns the plaintext key ONCE. Scopes are clamped to the agent ceiling — the key can never hold *, agents:manage, keys:manage, or policies:write.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Request Body schema: application/json
required
name
required
string

Human label for the key.

environment
string
Enum: "test" "live"

Environment. Defaults to test.

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 *, agents:manage, keys:manage, or policies:write. Defaults to wallets:read + payments:read/create.

expiresAt
string

Optional ISO-8601 expiry. A key past its expiry fails auth.

Responses

Request samples

Content type
application/json
{
  • "name": "ap-bot ci",
  • "environment": "test",
  • "scopes": [
    ],
  • "expiresAt": "2027-01-01T00:00:00.000Z"
}

Response samples

Content type
application/json
{
  • "id": "c1a2b3d4-...",
  • "key": "pm_test_Ab12Cd34Ef56_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  • "pubId": "Ab12Cd34Ef56",
  • "environment": "TEST",
  • "scopes": [
    ],
  • "expiresAt": null,
  • "createdAt": "2026-08-09T12:00:00.000Z"
}

Provision the agent's dedicated Safe

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "owners": [
    ],
  • "threshold": 1,
  • "chainId": 84532
}

Response samples

Content type
application/json
{
  • "agentId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  • "walletId": "string",
  • "address": { },
  • "status": "PENDING_DEPLOYMENT",
  • "chainId": 84532,
  • "threshold": 1
}

Issue a Safe-funded card bound to the agent

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

Request Body schema: application/json
required
perTransactionUsd
object or null

Per-transaction USD cap. null clears it.

dailyUsd
object or null

Rolling 24h USD cap. null clears it.

weeklyUsd
object or null

Rolling ISO-week USD cap. null clears it.

monthlyUsd
object or null

Calendar-month USD cap. null clears it.

blockedMcc
Array of strings

MCCs to decline. Replaces the existing list.

allowedMcc
Array of strings or null

When set, only these MCCs are allowed. null clears the allowlist (allow anything not blocked).

Responses

Request samples

Content type
application/json
{
  • "perTransactionUsd": "250.00",
  • "dailyUsd": "500.00",
  • "weeklyUsd": "2000.00",
  • "monthlyUsd": "5000.00",
  • "blockedMcc": [
    ],
  • "allowedMcc": [
    ]
}

Response samples

Content type
application/json
{
  • "cardId": "6ee0b2a0-3c8c-4f49-9d12-bd55b15f02b1",
  • "stripeCardId": "ic_1NXxxx",
  • "last4": "4242",
  • "safeAddress": "0x1111111111111111111111111111111111111111",
  • "status": "active"
}

The agent's merged audit timeline

Newest-first merge of the agent’s payments, card authorizations, and policy decisions. Read-only.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Agent id

query Parameters
limit
number
Example: limit=50

Max items (1–200). Defaults to 50.

Responses

Response samples

Content type
application/json
{
  • "agentId": "string",
  • "items": [
    ]
}

Authorize an x402 payment

Screens the payTo (OFAC), enforces the agent policy + spend caps (reserve-at-sign), and returns a signed X-PAYMENT header to retry the 402-protected request with. The payer is the agent Safe; the authorization is verified on-chain (EIP-1271) and bounded by the SessionKeyValidator.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
scheme
required
string
Enum: "exact" "upto"

x402 payment scheme.

network
required
string

CAIP-2 network id (EVM only).

amount
required
string

Atomic token units (for upto, the ceiling).

asset
required
string

Token contract address (USDC).

payTo
required
string

Recipient address (screened as the counterparty).

maxTimeoutSeconds
required
number
domainName
string
Default: "USD Coin"

EIP-712 domain name hint (402 extra.name).

domainVersion
string
Default: "2"

EIP-712 domain version hint (402 extra.version).

resource
string

The protected resource URL (audit only).

Responses

Request samples

Content type
application/json
{
  • "scheme": "exact",
  • "network": "eip155:84532",
  • "amount": "10000",
  • "asset": "string",
  • "payTo": "string",
  • "maxTimeoutSeconds": 60,
  • "domainName": "USD Coin",
  • "domainVersion": "2",
  • "resource": "string"
}

Response samples

Content type
application/json
{
  • "xPayment": "string",
  • "nonce": "string",
  • "reservationId": "string",
  • "from": "string",
  • "payTo": "string",
  • "amountUsd": "string",
  • "authorization": {
    }
}

Report x402 settlement

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "nonce": "string",
  • "txHash": "string",
  • "actualAmount": "string"
}

Response samples

Content type
application/json
{
  • "nonce": "string",
  • "status": "SETTLED"
}

wallets

Create a multisig wallet

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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).

Responses

Request samples

Content type
application/json
{
  • "name": "Acme Treasury",
  • "owners": [
    ],
  • "threshold": 1,
  • "chainId": 84532
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "address": { },
  • "status": "PENDING_DEPLOYMENT",
  • "chainId": { },
  • "threshold": 0,
  • "predictedAddress": true,
  • "name": "string",
  • "owners": [
    ],
  • "balances": [
    ],
  • "createdAt": "string"
}

List wallets

Tenant-scoped, newest first.

Authorizations:
apiKeyAuthprivyBearer
query Parameters
skip
string
take
string

Responses

Response samples

Content type
application/json
{
  • "wallets": [
    ],
  • "total": 0,
  • "skip": 0,
  • "take": 0
}

Transactions awaiting an owner’s signature

Pending Safe transactions across your wallets. Pass ?owner=0x… to get only those a specific owner has not yet signed (their co-sign queue).

Authorizations:
apiKeyAuthprivyBearer
query Parameters
owner
string

Responses

Response samples

Content type
application/json
{
  • "pending": [
    ]
}

Get a Safe transaction (with collected signatures)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
txId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "walletId": "string",
  • "to": "string",
  • "value": "string",
  • "data": "string",
  • "safeTxHash": { },
  • "status": "string",
  • "signers": [
    ],
  • "signatureCount": 0,
  • "threshold": 0,
  • "createdAt": "string"
}

Get a wallet

Includes live on-chain balances.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "address": { },
  • "status": "PENDING_DEPLOYMENT",
  • "chainId": { },
  • "threshold": 0,
  • "predictedAddress": true,
  • "name": "string",
  • "owners": [
    ],
  • "balances": [
    ],
  • "createdAt": "string"
}

List a wallet’s Safe transactions

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
query Parameters
skip
string
take
string

Responses

Propose a Safe transaction

Builds and pins a SafeTx (to/value/data). Returns the safeTxHash to sign.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "to": "0x036CbD…",
  • "value": "0",
  • "data": "0xa9059cbb…",
  • "ownerAddress": "string"
}

Submit an owner signature

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
txId
required
string
Request Body schema: application/json
required
signature
required
string

Raw secp256k1 signature over the 32-byte safeTxHash (NOT personal_sign).

Responses

Request samples

Content type
application/json
{
  • "signature": "0x…"
}

Execute a threshold-met transaction on-chain

Authorizations:
apiKeyAuthprivyBearer
path Parameters
txId
required
string
Request Body schema: application/json
required
ownerAddress
string

Owner address to act as. Optional for single-owner wallets.

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Cancel a pending transaction

Authorizations:
apiKeyAuthprivyBearer
path Parameters
txId
required
string
Request Body schema: application/json
required
ownerAddress
string

Owner address to act as. Optional for single-owner wallets.

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Propose adding an owner

Proposes an owner-admin SafeTx; the wallet threshold of owners must sign it.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "newOwner": "string",
  • "threshold": 2,
  • "role": "ADMIN_OWNER",
  • "ownerAddress": "string"
}

Propose removing an owner

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
addr
required
string

Owner address to remove

Request Body schema: application/json
required
threshold
required
number

Resulting signature threshold (1..ownerCount-1).

ownerAddress
string

Acting owner (ADMIN_OWNER). Optional if sole owner.

Responses

Request samples

Content type
application/json
{
  • "threshold": 1,
  • "ownerAddress": "string"
}

Propose swapping an owner for a new address

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
addr
required
string

Existing owner address to replace

Request Body schema: application/json
required
newOwner
required
string

The replacement owner address (EIP-55).

ownerAddress
string

Acting owner (ADMIN_OWNER). Optional if sole owner.

Responses

Request samples

Content type
application/json
{
  • "newOwner": "string",
  • "ownerAddress": "string"
}

Propose changing the signature threshold

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
threshold
required
number

New signature threshold (1..ownerCount).

ownerAddress
string

Acting owner (ADMIN_OWNER). Optional if sole owner.

Responses

Request samples

Content type
application/json
{
  • "threshold": 2,
  • "ownerAddress": "string"
}

balance

Where the money is: smart account and org account balances

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.

Authorizations:
apiKeyAuthprivyBearer
query Parameters
ensure
string
Enum: "true" "false"

Responses

Response samples

Content type
application/json
{
  • "chainId": 84532,
  • "chainName": "Base Sepolia",
  • "testnet": true,
  • "asset": {
    },
  • "primary": "SMART_ACCOUNT",
  • "accounts": [
    ],
  • "funding": "FAUCET",
  • "partial": true,
  • "observedAt": "2026-09-16T12:00:00.000Z"
}

faucet

Fund a wallet from the sandbox faucet

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Wallet id to fund.

Request Body schema: application/json
required
asset
string
Enum: "usdc" "eth"

Asset to drip. Defaults to usdc.

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.

Responses

Request samples

Content type
application/json
{
  • "asset": "usdc",
  • "amount": "250"
}

Response samples

Content type
application/json
{
  • "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"
}

Add Demo USD to one of your accounts

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
asset
string
Enum: "usdc" "eth"

Asset to drip. Defaults to usdc.

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.

Responses

Request samples

Content type
application/json
{
  • "asset": "usdc",
  • "amount": "250",
  • "account": "SMART_ACCOUNT"
}

Response samples

Content type
application/json
{
  • "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"
}

List faucet drips

Tenant-scoped, newest first.

Authorizations:
apiKeyAuthprivyBearer
query Parameters
walletId
string

Responses

Response samples

Content type
application/json
{
  • "drips": [
    ]
}

Get a faucet drip

Authorizations:
apiKeyAuthprivyBearer
path Parameters
dripId
required
string

Responses

Response samples

Content type
application/json
{
  • "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"
}

directory

Resolve a handle or email to a destination

Exact match only. Email resolution requires the target to have opted in.

Authorizations:
apiKeyAuthprivyBearer
query Parameters
handle
string
email
string

Responses

Response samples

Content type
application/json
{
  • "handle": "acme-treasury",
  • "displayName": { },
  • "address": "0x7Fb2…c41A",
  • "chainId": 84532,
  • "verified": true
}

Claim or update your payment handle

Points an @handle at one of your wallets so others can pay you by name.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

email
string

Contact email for email resolution.

Responses

Request samples

Content type
application/json
{
  • "handle": "acme-treasury",
  • "walletId": "w1",
  • "discoverableByEmail": false,
  • "email": "string"
}

Response samples

Content type
application/json
{
  • "handle": "acme-treasury",
  • "displayName": { },
  • "address": "0x7Fb2…c41A",
  • "chainId": 84532,
  • "verified": true
}

contacts

Save a payee to the address book

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
label
required
string

Short label used as @label at pay time.

displayName
string
notes
string
required
object (ContactDestinationInput)

Responses

Request samples

Content type
application/json
{
  • "label": "acme",
  • "displayName": "Acme Robotics",
  • "notes": "string",
  • "destination": {
    }
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "label": "string",
  • "displayName": { },
  • "notes": { },
  • "destination": {
    },
  • "createdAt": "string"
}

List saved contacts

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "contacts": [
    ]
}

Get a contact

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "label": "string",
  • "displayName": { },
  • "notes": { },
  • "destination": {
    },
  • "createdAt": "string"
}

Update a contact

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
displayName
string
notes
string
object (ContactDestinationInput)

Responses

Request samples

Content type
application/json
{
  • "displayName": "string",
  • "notes": "string",
  • "destination": {
    }
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "label": "string",
  • "displayName": { },
  • "notes": { },
  • "destination": {
    },
  • "createdAt": "string"
}

Delete a contact

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

identity

Start a KYC or KYB verification session

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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).

email
string

Subject contact email; defaults to the member email.

country
string

ISO-3166 alpha-2 country code.

Responses

Request samples

Content type
application/json
{
  • "kind": "KYC",
  • "memberId": "string",
  • "legalName": "string",
  • "email": "string",
  • "country": "DE"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "kind": "KYC",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "legalName": "string",
  • "status": "CREATED",
  • "requirements": [
    ],
  • "credentialId": { },
  • "client": {
    },
  • "createdAt": "string",
  • "updatedAt": "string",
  • "completedAt": { }
}

List verification sessions

Authorizations:
apiKeyAuthprivyBearer
query Parameters
subject_type
required
string
subject_id
required
string

Responses

Response samples

Content type
application/json
{
  • "sessions": [
    ]
}

Get a verification session

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "kind": "KYC",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "legalName": "string",
  • "status": "CREATED",
  • "requirements": [
    ],
  • "credentialId": { },
  • "client": {
    },
  • "createdAt": "string",
  • "updatedAt": "string",
  • "completedAt": { }
}

Cancel a verification session

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "kind": "KYC",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "legalName": "string",
  • "status": "CREATED",
  • "requirements": [
    ],
  • "credentialId": { },
  • "client": {
    },
  • "createdAt": "string",
  • "updatedAt": "string",
  • "completedAt": { }
}

Advance a sandbox session one step (TEST environment, mock provider only)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "kind": "KYC",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "legalName": "string",
  • "status": "CREATED",
  • "requirements": [
    ],
  • "credentialId": { },
  • "client": {
    },
  • "createdAt": "string",
  • "updatedAt": "string",
  • "completedAt": { }
}

List canonical identities in the tenant

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "identities": [
    ]
}

Get-or-create the identity for the tenant or one of its members

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
subjectType
required
string
Enum: "TENANT" "TENANT_MEMBER"

TENANT = this organization; TENANT_MEMBER needs memberId.

memberId
string

TenantMember id — required for TENANT_MEMBER.

Responses

Request samples

Content type
application/json
{
  • "subjectType": "TENANT",
  • "memberId": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "did": "did:safebank:cabc…",
  • "identityType": "PERSON",
  • "status": "ACTIVE",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "primarySmartAccountId": { },
  • "credentialAssuranceLevel": { },
  • "createdAt": "string"
}

Fetch one identity

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "did": "did:safebank:cabc…",
  • "identityType": "PERSON",
  • "status": "ACTIVE",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "primarySmartAccountId": { },
  • "credentialAssuranceLevel": { },
  • "createdAt": "string"
}

Wallet bindings of an identity (all statuses — history included)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "wallets": [
    ]
}

Start binding a wallet — returns the challenge the holder signs

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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"

Responses

Request samples

Content type
application/json
{
  • "walletAddress": "string",
  • "chainId": 0,
  • "walletType": "EOA"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "identityId": "string",
  • "chainFamily": "string",
  • "chainId": { },
  • "walletAddress": "string",
  • "walletType": "EOA",
  • "controllerType": "SELF",
  • "verificationMethod": "SIGNATURE_CHALLENGE",
  • "status": "PENDING",
  • "validFrom": "string",
  • "validUntil": { },
  • "verifiedAt": { },
  • "challenge": "string"
}

Prove wallet control (signature over the challenge); completes rotations too

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
bindingId
required
string
Request Body schema: application/json
required
signature
required
string

EIP-191 signature over the returned challenge.

Responses

Request samples

Content type
application/json
{
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "identityId": "string",
  • "chainFamily": "string",
  • "chainId": { },
  • "walletAddress": "string",
  • "walletType": "EOA",
  • "controllerType": "SELF",
  • "verificationMethod": "SIGNATURE_CHALLENGE",
  • "status": "PENDING",
  • "validFrom": "string",
  • "validUntil": { },
  • "verifiedAt": { }
}

Rotate to a new wallet — returns the NEW pending binding + challenge; verifying it retires the old one atomically (identity continuity)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
bindingId
required
string
Request Body schema: application/json
required
newWalletAddress
required
string

The replacement wallet address.

Responses

Request samples

Content type
application/json
{
  • "newWalletAddress": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "identityId": "string",
  • "chainFamily": "string",
  • "chainId": { },
  • "walletAddress": "string",
  • "walletType": "EOA",
  • "controllerType": "SELF",
  • "verificationMethod": "SIGNATURE_CHALLENGE",
  • "status": "PENDING",
  • "validFrom": "string",
  • "validUntil": { },
  • "verifiedAt": { },
  • "challenge": "string"
}

Selective disclosure: prove one claim against the on-chain claims root

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
claim
required
string

Responses

List credentials

Authorizations:
apiKeyAuthprivyBearer
query Parameters
subject_type
required
string
subject_id
required
string

Responses

Response samples

Content type
application/json
{
  • "credentials": [
    ]
}

Get a credential

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "kind": "PERSON_IDENTITY",
  • "subjectType": "TENANT",
  • "subjectId": "string",
  • "status": "ACTIVE",
  • "legalName": "string",
  • "issuedAt": "string",
  • "expiresAt": { },
  • "revokedAt": { },
  • "revokedReason": { },
  • "subjectDid": { },
  • "credentialHash": { },
  • "issuerKind": "PLATFORM"
}

Cached credential status with freshness anchors

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "status": "ACTIVE",
  • "revokedReason": { },
  • "statusRefreshedAt": { },
  • "statusSource": { }
}

Synchronously re-read the provider status (the high-value freshness path)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "status": "ACTIVE",
  • "revokedReason": { },
  • "statusRefreshedAt": { },
  • "statusSource": { }
}

The signed canonical credential document (holder read; 404 for legacy unsigned rows)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "document": { },
  • "signature": "string",
  • "credentialHash": "string",
  • "nonce": "string",
  • "issuerRef": "string",
  • "schemaVersion": "string"
}

Mint a one-time cross-device handoff link (rendered as a QR code)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "url": "string",
  • "expiresAt": "string"
}

Save a payout destination (requires an active KYB credential)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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).

email
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.

Responses

Request samples

Content type
application/json
{
  • "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"
}

Response samples

Content type
application/json
{
  • "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"
}

List payout destinations

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "destinations": [
    ]
}

Fetch one payout destination

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "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"
}

Update label/priority/fallback consent (the identifier itself is immutable)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
label
string

Display label.

priority
number

Ordering preference among own destinations.

allowAutomaticFallback
boolean

Consent to automatic fallback routing to this destination (spec rule 14).

Responses

Request samples

Content type
application/json
{
  • "label": "string",
  • "priority": 0,
  • "allowAutomaticFallback": true
}

Response samples

Content type
application/json
{
  • "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"
}

Revoke a destination (soft — history survives, routing excludes it)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "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"
}

Make a VERIFIED destination the default payout preference

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "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"
}

Verify destination ownership — signed EIP-712 proof (production, EVM) or sandbox stub

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "signature": "string",
  • "nonce": "string",
  • "expiresAt": "string"
}

Response samples

Content type
application/json
{
  • "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"
}

Mint a single-use presentation challenge (audience + nonce bound)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
purpose
required
string

What the presentation authorizes.

identityId
string

Expected holder identity, when known.

paymentId
string

Payment the presentation is scoped to.

Responses

Request samples

Content type
application/json
{
  • "purpose": "payment.approve",
  • "identityId": "string",
  • "paymentId": "string"
}

Response samples

Content type
application/json
{
  • "nonce": "string",
  • "audience": "string",
  • "domainTag": "string",
  • "purpose": "string",
  • "expiresAt": "string"
}

Verify a wallet-signed presentation; consumes its challenge either way

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "nonce": "string",
  • "holderDid": "did:safebank:cabc…",
  • "signature": "string",
  • "signerAddress": "string",
  • "credentialIds": [
    ],
  • "expiresAt": "string"
}

Response samples

Content type
application/json
{
  • "verified": true,
  • "holderDid": "string",
  • "credentialResults": [
    ],
  • "reasonCodes": [
    ],
  • "presentationId": "string"
}

Evaluate credential requirements for an action

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
action
required
string
Enum: "payments.create" "invoices.pay" "ramps.offramp" "claims.claim"

Responses

Request samples

Content type
application/json
{
  • "action": "payments.create"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "subjectAddress": "string",
  • "schema": "string",
  • "mode": "synthetic",
  • "maxPrincipal": "string",
  • "riskTier": 0,
  • "profile": { },
  • "permitDigest": "string",
  • "issuerAddress": "string",
  • "expiresAt": "string",
  • "status": "string"
}

policies

The ACTIVE payment policy (404 when none)

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "policyId": { },
  • "version": 0,
  • "rules": { },
  • "status": "ACTIVE",
  • "credentialId": { },
  • "activatedAt": { }
}

Supersede the active policy with a new version (returns the Safe attestation to sign)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
rules
required
object

Structured rules: maximumFeeMinor, maximumAmountUsd, allowedRails, allowedAssets, allowedChains, approvals[{aboveUsd, minimumApprovals}]. Unknown keys are refused.

Responses

Request samples

Content type
application/json
{
  • "rules": { }
}

Response samples

Content type
application/json
{
  • "policyId": { },
  • "version": 0,
  • "rules": { },
  • "status": "ACTIVE",
  • "credentialId": { },
  • "activatedAt": { },
  • "attestation": {
    }
}

Attach the org-Safe attestation to the active policy version

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
signature
required
string

Safe signature blob over the attestation hash (EIP-1271).

Responses

Request samples

Content type
application/json
{
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "policyId": { },
  • "version": 0,
  • "rules": { },
  • "status": "ACTIVE",
  • "credentialId": { },
  • "activatedAt": { }
}

All policy versions, newest first

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "policies": [
    ]
}

Create a policy

Compiles the document to an immutable v1 (IR + sha256) and makes it active.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "name": "AP bot guardrails",
  • "document": {
    }
}

Response samples

Content type
application/json
{
  • "policyId": "string",
  • "name": "string",
  • "status": "ACTIVE",
  • "activeVersionId": { },
  • "activeVersion": { },
  • "createdAt": "string"
}

List policies

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "policies": [
    ],
  • "total": 0
}

Evaluate a policy (dry-run)

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "policyId": "string",
  • "subjectType": "wallet",
  • "subjectId": "string",
  • "amountUsd": "120.00",
  • "mcc": "5411",
  • "counterparty": "string"
}

Response samples

Content type
application/json
{
  • "allow": true,
  • "reason": { },
  • "policyId": { },
  • "policyVersion": { },
  • "sha256": { },
  • "ruleTrace": [
    ],
  • "decisionLogId": "string"
}

Get a policy

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "policyId": "string",
  • "name": "string",
  • "status": "ACTIVE",
  • "activeVersionId": { },
  • "activeVersion": { },
  • "createdAt": "string"
}

Archive a policy

Archives the policy and detaches it from every subject.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Commit a new version

Appends an immutable version and makes it the active one.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
document
required
object

A new document — committed as the next immutable version.

Responses

Request samples

Content type
application/json
{
  • "document": { }
}

Response samples

Content type
application/json
{
  • "versionId": "string",
  • "version": 0,
  • "sha256": "string",
  • "ir": { },
  • "createdAt": "string"
}

List a policy’s versions

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "versions": [
    ],
  • "total": 0
}

Attach a policy to a subject

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
subjectType
required
string
Enum: "wallet" "card" "agent" "treasury_account"
subjectId
required
string

Id of the wallet / card / agent / treasury account.

Responses

Request samples

Content type
application/json
{
  • "subjectType": "wallet",
  • "subjectId": "string"
}

Response samples

Content type
application/json
{
  • "attachmentId": "string",
  • "policyId": "string",
  • "subjectType": "wallet",
  • "subjectId": "string",
  • "attachedAt": "string"
}

List a policy’s active attachments

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Detach a policy from a subject

Authorizations:
apiKeyAuthprivyBearer
path Parameters
attachmentId
required
string

Responses

2fa

List your enrolled second factors

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "factors": [
    ],
  • "requiredFactors": 0,
  • "usableFactors": 0
}

Begin enrolling a second factor

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
type
required
string
Enum: "EMAIL" "SMS" "TOTP" "PRIVY_MFA"
email
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".

Responses

Request samples

Content type
application/json
{
  • "type": "EMAIL",
  • "email": "string",
  • "phoneE164": "string",
  • "label": "string"
}

Response samples

Content type
application/json
{
  • "factorId": "string",
  • "type": "EMAIL",
  • "status": "string",
  • "hint": "string",
  • "secretBase32": "string",
  • "otpauthUri": "string",
  • "signerAddress": "string"
}

Prove control of a channel and activate the factor

Authorizations:
apiKeyAuthprivyBearer
path Parameters
factorId
required
string
Request Body schema: application/json
required
code
string

6-digit code (EMAIL / SMS / TOTP).

signature
string

EIP-712 signature (PRIVY_MFA).

Responses

Request samples

Content type
application/json
{
  • "code": "string",
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "type": "EMAIL",
  • "status": "PENDING",
  • "label": { },
  • "hint": "string",
  • "verifiedAt": { },
  • "usableAt": { },
  • "usableNow": true,
  • "lastUsedAt": { },
  • "createdAt": "string"
}

Revoke a second factor

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).

Authorizations:
apiKeyAuthprivyBearer
path Parameters
factorId
required
string

Responses

Read a pending transaction challenge

Authorizations:
apiKeyAuthprivyBearer
path Parameters
challengeId
required
string

Responses

Deliver a code for one factor

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
challengeId
required
string
Request Body schema: application/json
required
factorId
required
string

Which enrolled factor to deliver the code to.

Responses

Request samples

Content type
application/json
{
  • "factorId": "string"
}

Verify one factor against a challenge

Repeat until satisfiedFactors reaches requiredFactors, then replay the original request with the X-SafeBank-2FA-Challenge header.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
challengeId
required
string
Request Body schema: application/json
required
factorId
required
string
code
string

6-digit code (EMAIL / SMS / TOTP).

signature
string

EIP-712 signature (PRIVY_MFA).

Responses

Request samples

Content type
application/json
{
  • "factorId": "string",
  • "code": "string",
  • "signature": "string"
}

Read the tenant transaction-protection settings

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "enabled": true,
  • "coolingOffSeconds": 0,
  • "thresholdUsd": "string",
  • "requiredFactors": 0,
  • "updatedAt": { }
}

Update the tenant transaction-protection settings

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
enabled
boolean
coolingOffSeconds
number >= 86400

Minimum 86400 (24h) while enabled.

thresholdUsd
string
requiredFactors
number >= 1

Responses

Request samples

Content type
application/json
{
  • "enabled": true,
  • "coolingOffSeconds": 86400,
  • "thresholdUsd": "100",
  • "requiredFactors": 1
}

Response samples

Content type
application/json
{
  • "enabled": true,
  • "coolingOffSeconds": 0,
  • "thresholdUsd": "string",
  • "requiredFactors": 0,
  • "updatedAt": { }
}

treasury

Create a treasury account

Creates one Safe per bucket (202 — CREATE2 addresses are usable immediately, deployment is async). Sandbox-only for now.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "name": "Acme Treasury",
  • "owners": [
    ],
  • "threshold": 0,
  • "chainId": 0,
  • "buckets": [
    ]
}

Response samples

Content type
application/json
{
  • "accountId": "string",
  • "name": "string",
  • "buckets": [
    ],
  • "totalUsd": { },
  • "createdAt": "string"
}

List treasury accounts

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "accounts": [
    ],
  • "total": 0
}

Get a treasury account

Live bucket balances, drift vs targetBps, and accrued simulated yield. A bucket whose balance cannot be read right now reports null (never zero).

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "accountId": "string",
  • "name": "string",
  • "buckets": [
    ],
  • "totalUsd": { },
  • "createdAt": "string"
}

Create a rule

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "type": "SWEEP_EXCESS",
  • "sourceBucketId": "string",
  • "destBucketId": "string",
  • "thresholdUsd": "1000.00",
  • "targetUsd": "500.00",
  • "intervalSeconds": 0,
  • "enabled": true
}

Response samples

Content type
application/json
{
  • "ruleId": "string",
  • "accountId": "string",
  • "type": "SWEEP_EXCESS",
  • "sourceBucketId": { },
  • "destBucketId": { },
  • "thresholdUsd": { },
  • "targetUsd": { },
  • "intervalSeconds": 0,
  • "enabled": true,
  • "lastFiredAt": { },
  • "createdAt": "string"
}

List rules

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "rules": [
    ],
  • "total": 0
}

Update a rule (thresholds / cadence / enabled)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
ruleId
required
string
Request Body schema: application/json
required
thresholdUsd
string
targetUsd
string
intervalSeconds
number
enabled
boolean

Responses

Request samples

Content type
application/json
{
  • "thresholdUsd": "string",
  • "targetUsd": "string",
  • "intervalSeconds": 0,
  • "enabled": true
}

Response samples

Content type
application/json
{
  • "ruleId": "string",
  • "accountId": "string",
  • "type": "SWEEP_EXCESS",
  • "sourceBucketId": { },
  • "destBucketId": { },
  • "thresholdUsd": { },
  • "targetUsd": { },
  • "intervalSeconds": 0,
  • "enabled": true,
  • "lastFiredAt": { },
  • "createdAt": "string"
}

Delete a rule

Authorizations:
apiKeyAuthprivyBearer
path Parameters
ruleId
required
string

Responses

Propose a manual sweep

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).

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
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).

Responses

Request samples

Content type
application/json
{
  • "sourceBucketId": "string",
  • "destBucketId": "string",
  • "amountUsd": "250.00",
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "sweepId": "string",
  • "accountId": "string",
  • "ruleId": { },
  • "sourceBucketId": "string",
  • "destBucketId": "string",
  • "amountUsd": "string",
  • "status": "PROPOSED",
  • "paymentId": { },
  • "paymentStatus": { },
  • "failureReason": { },
  • "createdAt": "string"
}

List sweeps

Includes the live status of each sweep’s linked payment.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "sweeps": [
    ],
  • "total": 0
}

ramps

Create a ramp

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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 simulated is live in the sandbox today.

Responses

Request samples

Content type
application/json
{
  • "walletId": "string",
  • "direction": "on",
  • "amount": "100.00",
  • "provider": "simulated"
}

Response samples

Content type
application/json
{
  • "rampId": "string",
  • "walletId": "string",
  • "direction": "ON",
  • "provider": "simulated",
  • "amountUsd": "string",
  • "status": "SUBMITTED",
  • "txHash": { },
  • "paymentId": { },
  • "paymentStatus": { },
  • "fiatRef": { },
  • "simulated": true,
  • "failureReason": { },
  • "createdAt": "string"
}

List ramps

Authorizations:
apiKeyAuthprivyBearer
query Parameters
walletId
string

Responses

Response samples

Content type
application/json
{
  • "ramps": [
    ],
  • "total": 0
}

Get a ramp

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "rampId": "string",
  • "walletId": "string",
  • "direction": "ON",
  • "provider": "simulated",
  • "amountUsd": "string",
  • "status": "SUBMITTED",
  • "txHash": { },
  • "paymentId": { },
  • "paymentStatus": { },
  • "fiatRef": { },
  • "simulated": true,
  • "failureReason": { },
  • "createdAt": "string"
}

invoices

Create an invoice (draft)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "payeeName": "Volt Components",
  • "description": "string",
  • "amountUsd": "120.00",
  • "payerAddress": "0x1111…",
  • "payeeAddress": "0x2222…",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "expiresAt": "string"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

List invoices

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "invoices": [
    ],
  • "total": 0
}

Send a verifiable bill to another tenant

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "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"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

List inbound bills addressed to us

Authorizations:
apiKeyAuthprivyBearer
query Parameters
verification
string
Enum: "UNVERIFIED" "VERIFIED" "FAILED"

Responses

Response samples

Content type
application/json
{
  • "bills": [
    ],
  • "total": 0
}

Get one inbound bill

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

Get an invoice

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Send an invoice

Provisions the 2-of-3 hold Safe (202 — async deploy) and returns funding info.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Mark an invoice delivered (attach evidence)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
evidence
string

Delivery evidence (note / URL / reference).

Responses

Request samples

Content type
application/json
{
  • "evidence": "string"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Release funds to the payee

Proposes the release payment; two of the three owners must sign to execute it.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
ownerAddress
string

Acting owner for the release/refund proposal (defaults to the sole on-chain owner).

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Refund funds to the payer

Proposes the refund payment; two of the three owners must sign to execute it.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
ownerAddress
string

Acting owner for the release/refund proposal (defaults to the sole on-chain owner).

Responses

Request samples

Content type
application/json
{
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Cancel an unfunded invoice

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "arbiterAddress": "string",
  • "chainId": 0,
  • "status": "DRAFT",
  • "holdWalletId": { },
  • "holdAddress": { },
  • "releasePaymentId": { },
  • "refundPaymentId": { },
  • "expiresAt": { },
  • "createdAt": "string"
}

Re-run verification on an inbound bill

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

Accept an inbound bill (overlay)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

Decline an inbound bill (overlay)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

Pay an inbound bill from one of our wallets

Direct payment to the payee; rides M-of-N if the source wallet is multi-owner.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
sourceWalletId
required
string

The wallet to pay the bill from.

ownerAddress
string

Acting owner for the payment (if the wallet is M-of-N).

Responses

Request samples

Content type
application/json
{
  • "sourceWalletId": "string",
  • "ownerAddress": "string"
}

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "amountUsd": "string",
  • "payerAddress": "string",
  • "payeeAddress": "string",
  • "payeeName": { },
  • "description": { },
  • "chainId": 0,
  • "payerTenantId": { },
  • "senderTenantId": { },
  • "senderAddress": { },
  • "verificationStatus": "UNVERIFIED",
  • "payerDecision": "ACCEPTED",
  • "payerPaymentId": { },
  • "sigExpiresAt": { },
  • "createdAt": "string"
}

Public invoice view (unauthenticated)

path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "invoiceId": "string",
  • "payeeName": { },
  • "description": { },
  • "amountUsd": "string",
  • "status": "DRAFT",
  • "holdAddress": { },
  • "chainId": 0
}

status

Account summary: balance, bills owed, activity, agent spend

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "account": {
    },
  • "netBalanceUsd": "string",
  • "balancePartial": true,
  • "wallets": [
    ],
  • "billsOwed": {
    },
  • "recentActivity": [
    ],
  • "agentSpend": [
    ],
  • "generatedAt": "string"
}

agreements

List built-in policy templates

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "templates": [
    ]
}

Create an agreement draft

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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)

Responses

Request samples

Content type
application/json
{
  • "kind": "INVOICE",
  • "sourceType": "CHAT",
  • "title": "Boat sale to Mike",
  • "description": "string",
  • "currency": "USD",
  • "authorizedTotalMinor": "8000000",
  • "parties": [
    ]
}

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "latestPolicyVersion": {
    },
  • "createdAt": "string",
  • "updatedAt": "string"
}

List agreements for the tenant

Authorizations:
apiKeyAuthprivyBearer
query Parameters
limit
required
string

Responses

Response samples

Content type
application/json
{
  • "agreements": [
    ]
}

Get an agreement

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "latestPolicyVersion": {
    },
  • "createdAt": "string",
  • "updatedAt": "string"
}

Update a draft (optimistic concurrency via expectedVersion)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
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

Responses

Request samples

Content type
application/json
{
  • "expectedVersion": 0,
  • "financingRequest": {
    },
  • "title": "string",
  • "description": "string",
  • "authorizedTotalMinor": "8000000"
}

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "latestPolicyVersion": {
    },
  • "createdAt": "string",
  • "updatedAt": "string"
}

Compile an authored policy or template into the deterministic IR

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
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)

Responses

Request samples

Content type
application/json
{
  • "authoredPolicy": { },
  • "template": {
    }
}

Response samples

Content type
application/json
{
  • "ok": true,
  • "issues": [
    ],
  • "policyVersion": {
    }
}

Re-validate the latest compiled policy against current parties

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "ok": true,
  • "issues": [
    ],
  • "canonicalHash": "string"
}

Simulate the latest policy under a what-if overlay

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
Array of objects (SimulateFactInput)
at
string

Evaluate as of this instant (ISO-8601 UTC).

object (SimulateDisputeInput)

Responses

Request samples

Content type
application/json
{
  • "injectFacts": [
    ],
  • "at": "string",
  • "openDispute": {
    }
}

Response samples

Content type
application/json
{
  • "before": { },
  • "after": { }
}

How to protect the funds for this agreement

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "provider": "onchain",
  • "escrowAddress": "string",
  • "dealId": "string",
  • "tokenAddress": "string",
  • "chainId": 0,
  • "amountMinor": "string",
  • "steps": [
    ],
  • "note": "string"
}

Sandbox-only: simulate a protected-funds deposit

Available only with the mock protection provider (no escrow configured). Routes through the same funding accounting/FSM the on-chain indexer uses.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
amountMinor
required
string

Deposit amount in integer minor units.

Responses

Request samples

Content type
application/json
{
  • "amountMinor": "8000000"
}

Freeze the draft into an immutable version and open acceptance

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "version": 0,
  • "docHash": "string",
  • "doc": { }
}

Bind a party slot to the calling tenant (counterparty joins)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
partyKey
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "did": "string",
  • "reference": "string"
}

Accept the exact reviewed terms (hash-bound)

The caller echoes the docHash + policyHash they reviewed; a mismatch (e.g. a concurrent amendment) is refused, so blind acceptance is impossible.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
partyKey
required
string
agreementHash
required
string

Echo of the reviewed agreement version docHash.

policyHash
required
string

Echo of the reviewed policy canonicalHash.

Responses

Request samples

Content type
application/json
{
  • "partyKey": "payee",
  • "agreementHash": "string",
  • "policyHash": "string"
}

Get the exact EIP-712 typed-data the payer must sign

Hashes are server-derived from the stored agreement/policy versions — the wallet signs what Permara will verify, nothing looser.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "scope": "ACTIVATION",
  • "stageId": "string",
  • "payer": "string",
  • "nonce": "string",
  • "expiresAt": "string"
}

Response samples

Content type
application/json
{
  • "typedData": { }
}

Submit a signed EIP-712 AgreementAuthorization

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "scope": "ACTIVATION",
  • "stageId": "string",
  • "payer": "string",
  • "nonce": "string",
  • "expiresAt": "string",
  • "signature": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "scope": "string",
  • "stageId": { },
  • "status": "string",
  • "agreementHash": "string",
  • "policyHash": "string",
  • "releaseManifestHash": "string",
  • "canonicalPayloadHash": "string",
  • "expiresAt": "string"
}

Submit a party confirmation (or refutation) for a proof requirement

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
requirementId
required
string
confirmed
required
boolean

true = the condition happened; false = it did not.

note
string

Responses

Request samples

Content type
application/json
{
  • "requirementId": "completion-confirmed",
  • "confirmed": true,
  • "note": "string"
}

Response samples

Content type
application/json
{
  • "observationId": "string",
  • "attestationId": "string"
}

Revoke your own attestation

Dependent accepted facts flip to REVOKED and the agreement re-evaluates — a stage that lost its proof returns to waiting.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
attestationId
required
string
Request Body schema: application/json
required
reason
required
string

Responses

Request samples

Content type
application/json
{
  • "reason": "entered by mistake"
}

The policy in plain sentences: conditions, rules and who still has to sign

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "draft": {
    },
  • "state": {
    }
}

The latest deterministic policy decision ("why is this waiting?")

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "decisionHash": "string",
  • "inputSnapshotHash": "string",
  • "evaluatedAt": "string",
  • "result": { }
}

Open a dispute — affected unreleased stages freeze immediately

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
reasonCode
required
string
narrative
string
affectedStageIds
Array of strings

Stage ids to freeze; omit for all unreleased stages.

Responses

Request samples

Content type
application/json
{
  • "reasonCode": "ITEM_NOT_AS_DESCRIBED",
  • "narrative": "string",
  • "affectedStageIds": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "state": "string",
  • "reasonCode": "string",
  • "openedByPartyKey": "string",
  • "openedAt": "string"
}

Resolve a dispute (mutual: only the counterparty of the opener may)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
disputeId
required
string
Request Body schema: application/json
required
resolution
required
string
Enum: "RELEASE" "REFUND"
note
string

Responses

Request samples

Content type
application/json
{
  • "resolution": "RELEASE",
  • "note": "string"
}

The Agreement Card — canonical plain-language projection

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Plain-language timeline + "why is this waiting?"

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "entries": [
    ],
  • "whyWaiting": [
    ]
}

The completed agreement’s portable proof

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Activate: acceptances complete + valid ACTIVATION authorization

Freezes the policy ACTIVE and spawns the runtime release rows and timeout timers. Releases stay withheld until funding covers them — activation never moves money.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "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": [
    ],
  • "latestPolicyVersion": {
    },
  • "createdAt": "string",
  • "updatedAt": "string"
}

Resolve a share link to the exact Agreement Card (public; token = capability)

path Parameters
token
required
string

Responses

Response samples

Content type
application/json
{
  • "partyKey": "string",
  • "partyDisplayName": "string",
  • "partyRole": "string",
  • "agreementId": "string",
  • "lifecycleState": "string",
  • "alreadyBound": true,
  • "card": { }
}

Consume the share link and bind its party slot to the calling tenant

Authorizations:
apiKeyAuthprivyBearer
path Parameters
token
required
string

Responses

Response samples

Content type
application/json
{
  • "agreementId": "string",
  • "partyKey": "string"
}

Register an event source (secret shown once)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
Request Body schema: application/json
required
name
required
string
requirementId
required
string

The proof requirement this source attests (from the policy).

Responses

Request samples

Content type
application/json
{
  • "name": "Title registry webhook",
  • "requirementId": "title-transferred"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "endpointId": "string",
  • "name": "string",
  • "requirementId": "string",
  • "status": "string",
  • "secret": "string",
  • "ingestPath": "string"
}

List event sources for an agreement (no secrets)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string

Responses

Response samples

Content type
application/json
{
  • "sources": [
    ]
}

Rotate the HMAC secret (new value shown once)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
sourceId
required
string

Responses

Response samples

Content type
application/json
{
  • "secret": "string"
}

Revoke an event source (ingest rejects immediately)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
sourceId
required
string

Responses

Delivery log — every ingest attempt and its outcome

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
sourceId
required
string

Responses

Response samples

Content type
application/json
{
  • "deliveries": [
    ]
}

Test console: a ready-to-send signed sample request for the current secret

Authorizations:
apiKeyAuthprivyBearer
path Parameters
agreementId
required
string
sourceId
required
string

Responses

Response samples

Content type
application/json
{
  • "method": "string",
  • "path": "string",
  • "headers": { },
  • "body": "string"
}

Deliver a signed external event (HMAC-authenticated, replay-fenced)

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.

path Parameters
endpointId
required
string

Responses

Response samples

Content type
application/json
{
  • "observationId": "string",
  • "attestationId": "string"
}

The tool manifest this principal may invoke through chat (registry-derived, scope-filtered)

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "schemaVersion": "string",
  • "generatedFor": "principal",
  • "writesEnabled": true,
  • "tools": [
    ]
}

This tenant's conversations, pinned first, then newest activity (the Home list)

The first page carries every pinned conversation, then the newest unpinned ones; before pages the unpinned segment only.

Authorizations:
apiKeyAuthprivyBearer
query Parameters
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.

Responses

Response samples

Content type
application/json
{
  • "sessions": [
    ],
  • "nextBefore": { }
}

Start a conversation. With `text`, the person's first words are sent as the first turn at once (stream events from cursor 0).

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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").

Responses

Request samples

Content type
application/json
{
  • "text": "pay @harborgoods 250 for the rope order",
  • "attachments": [
    ],
  • "clientTurnId": "string"
}

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "title": { },
  • "kind": "pay",
  • "agreementId": { },
  • "paymentId": { },
  • "extractionId": { },
  • "pinnedAt": { },
  • "lastActivityAt": "string",
  • "lastReply": { },
  • "attention": "SIGNATURE",
  • "createdAt": "string",
  • "provider": "anthropic",
  • "model": "string",
  • "promptVersion": "string"
}

Rename or pin a conversation

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
Request Body schema: application/json
required
title
string

A new title for the conversation (1..80 characters).

pinned
boolean

Pin (true) or unpin (false) on the Home list.

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "pinned": true
}

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "title": { },
  • "kind": "pay",
  • "agreementId": { },
  • "paymentId": { },
  • "extractionId": { },
  • "pinnedAt": { },
  • "lastActivityAt": "string",
  • "lastReply": { },
  • "attention": "SIGNATURE",
  • "createdAt": "string"
}

Fetch a chat session transcript

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string

Responses

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "title": { },
  • "kind": "pay",
  • "agreementId": { },
  • "paymentId": { },
  • "extractionId": { },
  • "pinnedAt": { },
  • "lastActivityAt": "string",
  • "lastReply": { },
  • "attention": "SIGNATURE",
  • "createdAt": "string",
  • "provider": "anthropic",
  • "model": "string",
  • "promptVersion": "string",
  • "messages": [
    ]
}

Record the payment the person signed from this conversation (the app calls this after POST /v1/offramp/payments; the assistant never creates one)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
Request Body schema: application/json
required
paymentId
required
string

The corridor payment the person signed from this conversation (POST /v1/offramp/payments). Must belong to the caller.

Responses

Request samples

Content type
application/json
{
  • "paymentId": "string"
}

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "title": { },
  • "kind": "pay",
  • "agreementId": { },
  • "paymentId": { },
  • "extractionId": { },
  • "pinnedAt": { },
  • "lastActivityAt": "string",
  • "lastReply": { },
  • "attention": "SIGNATURE",
  • "createdAt": "string"
}

Send a message; the assistant drafts through server-validated tools

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "text": "I'm selling my boat to Mike Reynolds for $80,000 — $10,000 deposit when we sign.",
  • "mode": "execute",
  • "clientTurnId": "string",
  • "hostConfirmations": [
    ],
  • "attachments": [
    ]
}

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "resultId": "string",
  • "correlationId": "string",
  • "mode": "execute",
  • "replayed": true,
  • "reply": "string",
  • "actions": [
    ],
  • "agreementId": { },
  • "card": { },
  • "clarifications": [
    ],
  • "reviewUrl": { },
  • "providerMeta": {
    },
  • "limits": {
    }
}

Persisted turn events after a cursor (resume/replay); the same log the SSE stream delivers live

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
query Parameters
cursor
string

Last seq already seen (default 0).

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Server-sent turn events (text/event-stream): id=seq, event=type, data=ChatEventResponse. Reconnect with ?cursor=<last seq>.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
query Parameters
cursor
string

Last seq already seen (default 0).

Responses

Cancel generation for an in-flight turn (needs its clientTurnId). Never cancels a submitted operation.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
sessionId
required
string
clientTurnId
required
string

Responses

Response samples

Content type
application/json
{
  • "status": "cancel_requested",
  • "note": "string"
}

payables

The tenant's inbound payables address (minted on first read)

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "address": "ap-x8k2m4p9q1z7@payables.permara.com",
  • "localPart": "string"
}

Sandbox: deliver an email to your own payables address

Runs the exact ingestion pipeline (scan → OCR → extraction → risk flags) without SES. Production requires PAYABLES_INGEST_SIMULATE=true.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
from
required
string
subject
string
text
string

Plain-text body.

Array of objects (SimulatedAttachmentInput)

Responses

Request samples

Content type
application/json
{
  • "from": "Acme Marine <billing@acmemarine.example>",
  • "subject": "Invoice 2041 — slip rental",
  • "text": "string",
  • "attachments": [
    ]
}

Response samples

Content type
application/json
{
  • "messageId": "string",
  • "status": "string",
  • "extractionId": { }
}

Upload a document (invoice/PO) for extraction — the authorized upload session behind chat

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "filename": "invoice-2041.pdf",
  • "contentType": "application/pdf",
  • "base64": "string"
}

Response samples

Content type
application/json
{
  • "uploadId": "string",
  • "status": "EXTRACTED",
  • "extractionId": "string",
  • "sha256": "string"
}

Inbound messages for the tenant

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "messages": [
    ]
}

Invoice extractions with their risk flags

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "extractions": [
    ]
}

One extraction: the render-ready facts, per-field confidence, corrections, flags

Authorizations:
apiKeyAuthprivyBearer
path Parameters
extractionId
required
string

Responses

Response samples

Content type
application/json
{
  • "extraction": {
    },
  • "flags": [
    ]
}

Correct an extracted field (audited; confidence becomes 1)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
extractionId
required
string
Request Body schema: application/json
required
field
required
string
Enum: "vendorName" "vendorEmail" "invoiceNumber" "currency" "totalMinor" "dueDate" "bankDetails" "poNumber" "paymentTerms" "issueDate" "subtotalMinor" "taxMinor" "buyerName"
value
required
string

Responses

Request samples

Content type
application/json
{
  • "field": "vendorName",
  • "value": "string"
}

Response samples

Content type
application/json
{
  • "extraction": {
    },
  • "flags": [
    ]
}

Approve the reviewed extraction → agreement draft (INVOICE, or PURCHASE for a purchase order)

Blocked while risk flags are OPEN or critical fields are missing.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
extractionId
required
string

Responses

Response samples

Content type
application/json
{
  • "agreementId": "string"
}

Reject an extraction (dismisses its open flags)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
extractionId
required
string

Responses

Resolve or dismiss an open risk flag (audited)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
flagId
required
string
Request Body schema: application/json
required
outcome
required
string
Enum: "RESOLVED" "DISMISSED"

Responses

Request samples

Content type
application/json
{
  • "outcome": "RESOLVED"
}

lending

Deploy a demo lending pool cohort (spec default economics)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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).

Responses

Request samples

Content type
application/json
{
  • "name": "Demo PO Pool A",
  • "subscriptionSeconds": 604800,
  • "originationSeconds": 2592000
}

Response samples

Content type
application/json
{
  • "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": {
    },
  • "environmentNotice": "string"
}

List pools with live chain state

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "pools": [
    ]
}

Pool detail with live chain state

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "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": {
    },
  • "environmentNotice": "string"
}

The calling tenant's LP position in this pool

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "poolId": "string",
  • "ownerAddress": "string",
  • "units": "string",
  • "deposited": "string",
  • "withdrawn": "string",
  • "claimed": "string",
  • "claimable": "string",
  • "phase": "string"
}

Subscribe test capital during OPEN

Test funds only. Contributions become locked when subscriptions close; repayment is not guaranteed.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string
Request Body schema: application/json
required
amount
required
string

Six-decimal integer atoms.

Responses

Request samples

Content type
application/json
{
  • "amount": "60000000000"
}

Response samples

Content type
application/json
{
  • "txRef": "string"
}

Withdraw at par strictly before the subscription cutoff

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string
Request Body schema: application/json
required
amount
required
string

Six-decimal integer atoms.

Responses

Request samples

Content type
application/json
{
  • "amount": "60000000000"
}

Response samples

Content type
application/json
{
  • "txRef": "string"
}

Permissionless subscription finalization after the cutoff

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "txRef": "string"
}

Permissionless runoff transition after the origination cutoff

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "txRef": "string"
}

Permissionless closure once every loan is repaid or written down

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "txRef": "string"
}

Claim the tenant's currently claimable proceeds (paid to the recorded owner wallet)

Authorizations:
apiKeyAuthprivyBearer
path Parameters
poolId
required
string

Responses

Response samples

Content type
application/json
{
  • "txRef": "string",
  • "amount": "string"
}

Register an APPROVED payables extraction as a financeable PO

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "poolId": "string",
  • "tradeOrderId": "string",
  • "extractionId": "string",
  • "supplierTenantId": "string",
  • "supplierWallet": "string",
  • "faceAmount": "20000000000"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "poId": "string",
  • "extractionId": "string",
  • "tradeOrderId": "string",
  • "borrowerAddress": "string",
  • "supplierWallet": "string",
  • "faceAmount": "string",
  • "status": "string"
}

Purchase orders the tenant borrows against or supplies

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "purchaseOrders": [
    ]
}

Supplier acceptance: sign the exact PO and payout wallet

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
minPrincipal
string

Supplier floor on financed principal (atoms); defaults to the PO face amount.

Responses

Request samples

Content type
application/json
{
  • "minPrincipal": "20000000000"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "poId": "string",
  • "extractionId": "string",
  • "tradeOrderId": "string",
  • "borrowerAddress": "string",
  • "supplierWallet": "string",
  • "faceAmount": "string",
  • "status": "string"
}

Issue the verifiable financial eligibility credential (synthetic evidence)

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.

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "poolId": "string",
  • "mode": "synthetic",
  • "riskTier": 2
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "subjectAddress": "string",
  • "schema": "string",
  • "mode": "synthetic",
  • "maxPrincipal": "string",
  • "riskTier": 0,
  • "profile": { },
  • "permitDigest": "string",
  • "issuerAddress": "string",
  • "expiresAt": "string",
  • "status": "string"
}

The tenant's eligibility credentials

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Request an underwriter-signed offer on a registered PO

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
poolId
required
string
poId
required
string

Canonical registered PO id (0x…32 bytes).

principal
required
string

Requested principal in atoms.

Responses

Request samples

Content type
application/json
{
  • "poolId": "string",
  • "poId": "string",
  • "principal": "20000000000"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "poolId": "string",
  • "poId": "string",
  • "borrowerAddress": "string",
  • "principal": "string",
  • "rateBps": 0,
  • "tenorSeconds": 0,
  • "graceSeconds": 0,
  • "deadline": "string",
  • "offerDigest": "string",
  • "status": "string"
}

Borrower acceptance binding the offer's exact digest

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "poolId": "string",
  • "poId": "string",
  • "borrowerAddress": "string",
  • "principal": "string",
  • "rateBps": 0,
  • "tenorSeconds": 0,
  • "graceSeconds": 0,
  • "deadline": "string",
  • "offerDigest": "string",
  • "status": "string"
}

Offer detail

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "poolId": "string",
  • "poId": "string",
  • "borrowerAddress": "string",
  • "principal": "string",
  • "rateBps": 0,
  • "tenorSeconds": 0,
  • "graceSeconds": 0,
  • "deadline": "string",
  • "offerDigest": "string",
  • "status": "string"
}

Draw the loan: atomic four-signature origination paying the supplier directly

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
offerId
required
string

An ACCEPTED lending offer id.

Responses

Request samples

Content type
application/json
{
  • "offerId": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "poolId": "string",
  • "poId": "string",
  • "borrowerAddress": "string",
  • "supplierWallet": "string",
  • "principal": "string",
  • "principalOutstanding": "string",
  • "interestDue": "string",
  • "status": "string",
  • "fundedAt": "string",
  • "maturityAt": "string",
  • "graceEndsAt": "string"
}

The tenant's loans

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "loans": [
    ]
}

Loan detail with live debt state

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "poolId": "string",
  • "poId": "string",
  • "borrowerAddress": "string",
  • "supplierWallet": "string",
  • "principal": "string",
  • "principalOutstanding": "string",
  • "interestDue": "string",
  • "status": "string",
  • "fundedAt": "string",
  • "maturityAt": "string",
  • "graceEndsAt": "string"
}

Repay up to a maximum: interest first, then principal, routed to the pool

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.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
maxAmount
required
string

Maximum the payer authorizes (atoms).

deadlineSeconds
number

Authorization validity in seconds (default 3600).

Responses

Request samples

Content type
application/json
{
  • "maxAmount": "20197260273",
  • "deadlineSeconds": 3600
}

Response samples

Content type
application/json
{
  • "txRef": "string",
  • "amount": "string",
  • "interestPortion": "string",
  • "principalPortion": "string",
  • "loanStatus": "string"
}

Permissionless deterministic default recognition after grace

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "txRef": "string"
}

trade

Draft a purchase order (structured terms, or seeded from an uploaded document)

Authorizations:
apiKeyAuthprivyBearer
Request Body schema: application/json
required
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)

Responses

Request samples

Content type
application/json
{
  • "sellerTenantId": "string",
  • "extractionId": "string",
  • "agreementId": "string",
  • "terms": {
    }
}

Response samples

Content type
application/json
{
  • "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
}

Trade orders where you are buyer or seller

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "orders": [
    ]
}

Trade order detail

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "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
}

Buyer edits the draft — bumps the version, voids prior signatures

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
required
object (TradeTermsInput)
required
Array of objects (TradeLineItemInput)
dueDays
number

Days until the invoice is due after acceptance.

deliveryTerms
string

Responses

Request samples

Content type
application/json
{
  • "terms": {
    }
}

Response samples

Content type
application/json
{
  • "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
}

Buyer signs the exact version and proposes it to the seller

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "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
}

Seller review: accept (countersign → Verified Sales Order), request changes, or reject

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
action
required
string
Enum: "accept" "request-changes" "reject"
note
string

Required note for request-changes.

Responses

Request samples

Content type
application/json
{
  • "action": "accept",
  • "note": "string"
}

Response samples

Content type
application/json
{
  • "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
}

Seller delivers against the sales order with attached evidence

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string
Request Body schema: application/json
required
note
string
evidenceUploadIds
Array of strings

Payables upload ids attached as delivery evidence.

Responses

Request samples

Content type
application/json
{
  • "note": "Delivered to pier 4, signed by receiving manager.",
  • "evidenceUploadIds": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "orderId": "string",
  • "status": "string",
  • "note": "string",
  • "evidenceHash": "string",
  • "deliveredAt": "string",
  • "acceptedAt": "string",
  • "invoiceId": "string"
}

Deliveries recorded against an order

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Buyer accepts the delivery — signs the acceptance and triggers invoice creation

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "orderId": "string",
  • "status": "string",
  • "note": "string",
  • "evidenceHash": "string",
  • "deliveredAt": "string",
  • "acceptedAt": "string",
  • "invoiceId": "string"
}

Invoices generated from your sales orders

Authorizations:
apiKeyAuthprivyBearer

Responses

Response samples

Content type
application/json
{
  • "invoices": [
    ]
}

Authorize and route the payment: to the financier (loan repayment) when financed, else to the seller

Re-verifies the whole document chain — identities, mutual sales-order signatures against the exact content, delivery acceptance, invoice match — before any funds move.

Authorizations:
apiKeyAuthprivyBearer
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "invoiceId": "string",
  • "route": "FINANCIER",
  • "amountAtoms": "string",
  • "interestPortion": "string",
  • "principalPortion": "string",
  • "sellerPortion": "string",
  • "remainingFinancingCost": "string",
  • "matchedChecks": { }
}