Skip to main content
The payments endpoints are where money moves. See Payments (concept) for the enforcement model and SDK payments for the TypeScript wrapper.

The payment object


POST /v1/payments

Sign and broadcast a USDC transfer.

Request

Response

201 Created:
The endpoint returns as soon as Privy accepts the signed RPC. The on-chain receipt arrives a few seconds later — poll GET /v1/payments/{id} or subscribe to payment.confirmed webhooks.

Enforcement layers

In order, before the response is built:
  1. Tally pre-check. The agent must exist in this (account, mode); the wallet must belong to the account; an active grant must exist; the policy (per-tx max, daily cap, recipient/contract allowlist, expiry) must permit the payment.
  2. Privy enclave. Independently re-validates the per-tx max and allowlists when signing. A compromised Tally server can’t sneak a payment past this check.
Pre-check failures (layer 1) return 4xx with a structured error code — see below. Enclave failures (layer 2) result in status: "failed" on the resulting payment.

Errors

See Errors for the response envelope.

Rate limit

POST /v1/payments uses the stricter payments bucket: 30 requests / 60 seconds per API key. See Rate limits.

GET /v1/payments/{id}

Retrieve a single payment by its Tally id. If the payment is still pending on Tally’s side and has a tx_hash, this call lazily refreshes from the chain — so polling GET /v1/payments/{id} is the canonical way to wait for a confirmation.

Request

Response

200 OK. Same shape as the POST /v1/payments response. status reflects the latest known state — if the chain has confirmed since the last call, status will have flipped to confirmed or failed.

Errors


Patterns

Poll until confirmed

Don’t poll faster than every 2 seconds — you’ll burn rate-limit budget without seeing a meaningfully fresher status.

Production: subscribe to webhooks instead

For production workloads, replace the polling loop with a webhook subscription to payment.confirmed and payment.failed. The event carries the same payment shape; verification helper lives in the SDK webhooks page.

Not yet exposed

  • GET /v1/payments — listing with status/agent/direction filters.
  • POST /v1/payments/{id}/refund — first-class refund handling.
For listing today, the dashboard’s Transactions tab is the source of truth.