Pocket Money - Relay API (0.4.0)

Download OpenAPI specification:

The Relay API lets Pocket Customers manage recipients, move money to other Pocket Customers, submit Batches of transfers, and reconcile balances and activity.

  • A Customer (cus_…) is the person or business represented by the API key. V1 operates on that Customer's funds and activity.
  • A Recipient is another Pocket Customer saved for future transfers.
  • A Transfer is money sent from the authenticated Customer to another Pocket Customer.
  • A Deposit is money received by the authenticated Customer.
  • A Batch groups one or more Customer-to-Customer transfers for submission and reconciliation.

Pocket publishes the Relay API as an OpenAPI specification rather than client SDKs.

API surface

Resource Purpose
Balances Read the authenticated Customer's current funds.
Recipients Manage a business Customer's payout roster.
Transactions Read inbound and outbound activity together.
Transfers Create and reconcile Customer-to-Customer transfers.
Deposits Reconcile money received by the Customer.
Batch transfers Submit and reconcile asynchronous Customer-to-Customer payouts.

This document is specification version 0.4.0, published under /v1.

Authentication and ownership

Send the API key as a bearer token:

Authorization: Bearer eak_v1_...

Every request runs as the Customer attached to that key. A source customer_id must match it. A resource owned by another Customer returns 404 as if it did not exist. Recipient and Batch operations require an authenticated business Customer.

The key must also contain every scope named by the operation. The V1 scopes are balances:read, recipients:read, recipients:write, transactions:read, transfers:read, transfers:write, deposits:read, batches:read and batches:write. Broad read and write scopes satisfy their corresponding granular scopes.

Transfers, deposits and transactions

An accepted internal transfer creates one txn_… ID. The source Customer sees a Transfer and the destination Customer sees a Deposit. Each Customer can also read its own Transaction view. Neither Customer gains access to the other's balance or unrelated activity.

Accepted outbound money moves from available to reserved. At settlement it leaves the source balance and is credited to the destination balance. A failed or voided movement remains visible and the reservation is released.

Amounts

Amounts are decimal strings in major currency units. USD accepts at most two decimal places. JSON numbers, commas, whitespace, scientific notation and negative values are rejected.

Idempotency

Recipient creation, Recipient replacement when a key is supplied, and Batch creation provide idempotent replay for 24 hours. Reuse a key only for an unchanged retry. A changed request during that period returns 409. At or after 24 hours, the key is treated as new.

Other request types retain an idempotency_key field, but V1 does not yet guarantee replay or duplicate suppression for those operations.

Pagination

List operations use opaque cursors. Pass next_cursor back as cursor with the same filters. Do not parse or construct cursors.

Payroll integration model

A payroll integration runs as one authenticated business Customer. That Customer owns the recipient roster, supplies the source balance and submits each Batch. Employees are destination Customers.

The normal flow is:

  1. Add or resolve each employee as a Recipient.
  2. Check the business Customer's available balance.
  3. Submit a Batch with the business Customer in source.customer_id.
  4. Reconcile the Batch, its items and the resulting Transfers.

Set up an employee for payroll

Add each employee to the authenticated business Customer's recipient roster. The Recipient has its own rcp_… ID. Once linked, its customer_id is the destination to use in a Batch.

POST /v1/customers/cus_01j8ma3wv3mepwabfxxs0yc395/recipients

A pending Recipient has customer_id: null and cannot receive a Batch item. Use capabilities.can_receive_transfers immediately before submission.

Read balances and activity

GET /v1/balances returns the authenticated Customer's USD balance:

{
  "data": [
    {
      "customer_id": "cus_01j8ma3wv3mepwabfxxs0yc395",
      "currency": "USD",
      "available": "2500.00",
      "settled": "2500.00",
      "reserved": "0.00",
      "as_of": "2026-07-31T09:15:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Use /v1/transactions for the combined activity feed, /v1/transfers for outbound movements and /v1/deposits for inbound movements. Every returned customer_id identifies the authenticated Customer's view.

Run a payroll batch

Submit one asynchronous Batch from the authenticated business Customer to its employee Customers:

{
  "idempotency_key": "a15e4ae4-52f3-460c-9c1c-5f6b7b90cc44",
  "source": {
    "customer_id": "cus_01j8ma3wv3mepwabfxxs0yc395"
  },
  "recipient_policy": "recipients_only",
  "items": [
    {
      "item_id": "line-001",
      "destination": {
        "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej"
      },
      "amount": "100.00",
      "currency": "USD",
      "reference": "EMP-1042"
    }
  ],
  "reference": "northwind-payroll-2026-07"
}

Acceptance does not reserve the whole Batch amount. Each item checks the source Customer's available balance when it runs. Use the item endpoint to reconcile every submitted item_id, including failures that never created a Transfer.

Send money to another Pocket customer

Create an internal transfer from the authenticated Customer to another Pocket Customer:

{
  "idempotency_key": "d9f80740-7f8e-4f16-b5cc-4fd5bf7d3b21",
  "source": {
    "customer_id": "cus_01j8ma3wv3mepwabfxxs0yc395"
  },
  "destination": {
    "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej"
  },
  "amount": "100.00",
  "currency": "USD",
  "reference": "payrun-2026-07",
  "memo": "July salary"
}

The source ID must match the Customer attached to the API key. The destination Customer's balance and private activity are never exposed to the sender.

Balances

Read the authenticated Customer's current balance.

List balances

Required scope: balances:read.

Return the balances held by the authenticated Customer. V1 returns the Customer's single USD balance. The customer_id on each result is the Customer attached to the API key.

Authorizations:
bearerAuth
query Parameters
currency
string (Currency)
Value: "USD"
Example: currency=USD

Only balances in this currency.

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Recipients

Recipients are business-owned roster resources identified by rcp_…. A pending Recipient has no matched Customer. A linked Recipient returns the Customer cus_… ID that Transfers and Batch items use as their destination.

Recipient resources belong to the authenticated business Customer. An authenticated individual Customer returns 403. Another Customer returns 404 when used as business_customer_id.

  • A Recipient id manages the roster resource; it is never a payment destination.
  • A linked Recipient's customer_id is the Customer destination for Transfers and Batch items. It is null while the Recipient is pending.
  • Adding a Recipient resolves one or more exact identifiers to an existing Customer. An incomplete or conflicting match creates nothing.
  • A Recipient never grants access to or changes a linked Customer.
  • The business supplies the recipient label. Pocket does not return the Customer's profile name, email, phone, government identity, KYC state, or onboarding reason.
  • Raw email and phone inputs are sensitive. Pocket never returns them or includes them in errors, logs, traces, metadata, events, or webhook subjects.

Pocket normalizes identity inputs before matching:

  • customer_id: exact Pocket cus_… ID.
  • paytag: surrounding whitespace and one optional leading @ removed, then normalized with Pocket's paytag case rules.
  • phone: E.164 international phone-number format.
  • email: surrounding whitespace trimmed, then compared case-insensitively after Pocket's email normalization.

Supply at least one identifier. When several are supplied, every value must resolve uniquely to the same Customer. A malformed identifier returns 400 with param naming the field. Conflicting matches, ambiguity, blocks, and unavailable targets return the same generic 404 recipient_not_found and create nothing.

Add a recipient to a business

Required scope: recipients:write.

Customer eligibility: authenticated business Customer only.

Create a Recipient (rcp_…) on this business's roster. Pocket first attempts to resolve one or more exact identifiers to an existing Customer. A linked Recipient returns that Customer's customer_id, which is the destination to use in internal Transfers and Batch items. The Recipient id manages the roster resource and is never a payment destination.

business_customer_id must identify the authenticated business Customer. Another Customer returns 404.

Lookup and assurance

Supply at least one of customer_id, exact paytag, email, or phone. You may supply several identifiers to increase confidence in the match. Every supplied identifier must resolve uniquely to the same Customer.

Government-ID and name lookup are not supported. Pocket matches email and phone only when Pocket has verified them.

When the identifiers do not resolve completely to one Customer, Pocket returns 404 recipient_not_found and creates nothing. This includes an unknown explicit customer_id, conflicting matches, ambiguous identity data, blocked relationships, and unavailable targets. The response does not identify which value failed.

Recipient data

label, reference, and metadata belong to this business's roster relationship. Pocket does not compare label with or replace it from the Customer's profile.

Retries and re-adding

idempotency_key is required. A new linked Recipient returns 201 Created. A request that identifies an existing non-removed Recipient returns 200 OK without changing its business-owned fields; use PUT to replace their mutable state.

Re-adding a removed Recipient restores its current roster resource as a new relationship epoch and returns 200 OK. The new request's label, reference, and metadata become the current business-owned fields.

Privacy

The response returns the Recipient id and a nullable resolved customer_id, but no Pocket profile name, email, phone, paytag, government identity, KYC state, onboarding state, or private capability reason. Raw email and phone are sensitive inputs: Pocket does not return them or include them in errors, ordinary logs, traces, metadata, events, or webhook subjects.

Pocket applies additional rate limits and abuse controls to identity resolution.

Authorizations:
bearerAuth
path Parameters
business_customer_id
required
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: cus_01j8ma3wv3mepwabfxxs0yc395

The authenticated business Customer whose recipient roster the API manages. An individual Customer returns 403. Another Customer returns 404.

Request Body schema: application/json
required
Any of
idempotency_key
required
string [ 1 .. 255 ] characters ^[^\x00]*\S[^\x00]*$

Binds this Recipient create request for 24 hours. During that period, an unchanged retry returns the existing result and a changed request returns 409. At or after 24 hours, the key is treated as new.

label
required
string [ 1 .. 120 ] characters ^[^\x00]*\S[^\x00]*$

Business-supplied display label.

customer_id
required
string (RecipientCustomerIdLookup) ^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$

Match by the customer's exact Pocket ID (cus_…). This value is not normalized.

paytag
string (RecipientPaytagLookup) [ 1 .. 32 ] characters .*\S.*

Match by exact paytag after trimming surrounding whitespace, removing at most one leading @, and applying Pocket's paytag case normalization.

email
string <email> (RecipientEmailLookup) <= 254 characters

Match by verified email after trimming surrounding whitespace and applying Pocket's case-insensitive email normalization. This is a sensitive lookup input and is never returned on the Recipient resource.

phone
string (RecipientPhoneLookup) ^\+[1-9][0-9]{1,14}$

Match by verified E.164 phone (for example, +61412345678). This is a sensitive lookup input and is never returned on the Recipient resource.

reference
string or null <= 255 characters ^[^\x00]*$

Optional business-owned reconciliation reference.

object (Metadata) <= 50 properties

Up to 50 caller-defined string key/value pairs. An empty object is valid.

Keys

  • 1–64 Unicode characters.
  • Compared exactly as supplied.
  • Not trimmed, case-folded, or Unicode-normalized.
  • Any Unicode character except NUL (U+0000).

OpenAPI 3.0 cannot express the key-length limit for arbitrary properties, so Pocket enforces it at runtime. An invalid key returns 400 invalid_request with param=metadata. The key is not echoed.

Values

  • String values only.
  • Empty values are allowed.
  • Maximum 256 Unicode characters.
  • NUL (U+0000) is not allowed.
  • Preserved exactly as supplied, without trimming or Unicode normalization.

An overlong value returns 400 invalid_request. param is metadata.<key> when the key is valid, or metadata when the key is invalid. The value is never echoed.

Privacy

The API shows metadata only in the Customer view where the caller set it. The API does not share metadata with money-movement counterparties. Use it for opaque business identifiers and non-sensitive labels only.

Do not include:

  • Government identity values.
  • Bank-account, routing, or payment-card details.
  • Passwords, secrets, access tokens, or credentials.
  • KYC documents.
  • Biometric or health information.
  • Names, email addresses, or phone numbers when a dedicated field exists.

Pocket may reject metadata that appears sensitive, but the caller remains responsible for the data it supplies.

Responses

Request samples

Content type
application/json
{
  • "idempotency_key": "add-supplier-88",
  • "label": "Northwind Supplies",
  • "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej",
  • "reference": "SUP-88"
}

Response samples

Content type
application/json
{
  • "id": "rcp_01k2p7m4sd6t8v0x3y5z9a1bcf",
  • "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej",
  • "label": "Taylor Reed",
  • "reference": "EMP-1042",
  • "association_status": "linked",
  • "status": "active",
  • "capabilities": {
    },
  • "metadata": {
    },
  • "created_at": "2026-07-31T09:05:00Z",
  • "updated_at": "2026-07-31T09:05:00Z"
}

List a business's recipients

Required scope: recipients:read.

Customer eligibility: authenticated business Customer only.

List this business's linked and pending Recipient resources. A linked Recipient returns its destination customer_id; a pending Recipient returns customer_id: null. The API returns business-owned relationship fields. It does not expose Customer profile, contact, KYC, onboarding, balance, activity, or payment details.

  • Default lists exclude removed recipients.
  • Use status=removed to list removed recipients.
  • Filter by relationship/association status, current capability, or exact business reference.
  • Filter by an exact linked customer_id.
  • q searches only this business's Recipient ID, label, reference, metadata keys and values, and linked customer_id; it never searches Pocket Customer identity data.
  • Retrieve one relationship from GET /v1/customers/{business_customer_id}/recipients/{recipient_id}.

Results are ordered by creation time and Recipient ID. Use order to return the oldest or newest Recipients first. A cursor is bound to the owning business Customer, order, and normalized status, association_status, can_receive_transfers, customer_id, reference, and q filters.

Authorizations:
bearerAuth
path Parameters
business_customer_id
required
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: cus_01j8ma3wv3mepwabfxxs0yc395

The authenticated business Customer whose recipient roster the API manages. An individual Customer returns 403. Another Customer returns 404.

query Parameters
status
string (RecipientStatus)
Enum: "active" "inactive" "removed"

Only recipients in this relationship state. Without this filter, the list excludes removed recipients.

association_status
string (RecipientAssociationStatus)
Enum: "linked" "pending" "unavailable"

Only recipients in this association state.

can_receive_transfers
boolean

Only recipients with this current advisory capability.

customer_id
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$

Only the linked Recipient for this exact Customer ID. Pending Recipients never match.

reference
string <= 255 characters ^[^\x00]*$

Exact business-owned recipient reference.

q
string [ 1 .. 255 ] characters ^[^\x00]*\S[^\x00]*$

Case-insensitive search over this business's label, reference, and metadata keys and values, plus exact/prefix Recipient ID and linked Customer ID matching. It never searches Customer names, paytags, email, or phone.

order
string
Default: "desc"
Enum: "asc" "desc"

Sort by creation time. desc returns newest first; asc returns oldest first. IDs break ties in the same direction.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "has_more": true,
  • "next_cursor": "string"
}

Retrieve a recipient

Required scope: recipients:read.

Customer eligibility: authenticated business Customer only.

Retrieve this business's linked or pending Recipient by recipient_id. Soft-removed Recipients are included. The response contains a nullable destination Customer ID and business-owned relationship fields, not private Customer data or matching inputs.

Authorizations:
bearerAuth
path Parameters
business_customer_id
required
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: cus_01j8ma3wv3mepwabfxxs0yc395

The authenticated business Customer whose recipient roster the API manages. An individual Customer returns 403. Another Customer returns 404.

recipient_id
required
string^rcp_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: rcp_01k2p7m4sd6t8v0x3y5z9a1bcf

The Recipient (rcp_…) owned by this business Customer.

Responses

Response samples

Content type
application/json
{
  • "id": "rcp_01k2p7m4sd6t8v0x3y5z9a1bcf",
  • "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej",
  • "label": "Taylor Reed",
  • "reference": "EMP-1042",
  • "association_status": "linked",
  • "status": "active",
  • "capabilities": {
    },
  • "metadata": {
    },
  • "created_at": "2026-07-31T09:05:00Z",
  • "updated_at": "2026-07-31T09:05:00Z"
}

Update a recipient

Required scope: recipients:write.

Customer eligibility: authenticated business Customer only.

Replace this business's mutable recipient state. Supply all of label, reference, status, and metadata.

  • label is the business's display name for the recipient.
  • reference is required but may be null to clear it.
  • status may be active or inactive.
  • metadata replaces the whole metadata object. Use {} to clear it.
  • idempotency_key is optional.

This changes only the Recipient resource. It does not change a linked Pocket Customer. A pending Recipient's lookup identifiers cannot be changed in V1.

active means the business considers the recipient active. It does not guarantee that the customer can receive a transfer.

  • Use capabilities.can_receive_transfers as the sole current inclusion check for payments restricted to registered recipients.
  • An active update cannot bypass private Customer state.
  • PUT does not restore a removed recipient. Re-add it through the recipient collection endpoint.
  • An unavailable state transition returns 409.
Authorizations:
bearerAuth
path Parameters
business_customer_id
required
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: cus_01j8ma3wv3mepwabfxxs0yc395

The authenticated business Customer whose recipient roster the API manages. An individual Customer returns 403. Another Customer returns 404.

recipient_id
required
string^rcp_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: rcp_01k2p7m4sd6t8v0x3y5z9a1bcf

The Recipient (rcp_…) owned by this business Customer.

Request Body schema: application/json
required
idempotency_key
string [ 1 .. 255 ] characters ^[^\x00]*\S[^\x00]*$

Optional. When supplied, binds this Recipient replacement for 24 hours. During that period, an unchanged retry returns the existing result and a changed request returns 409. At or after 24 hours, the key is treated as new.

label
required
string [ 1 .. 120 ] characters ^[^\x00]*\S[^\x00]*$

Business-supplied display label.

reference
required
string or null <= 255 characters ^[^\x00]*$

Set to null to clear.

status
required
string (RecipientWritableStatus)
Enum: "active" "inactive"

The recipient relationship states a business may request. Setting active changes only the business-owned recipient record and cannot bypass private Customer eligibility.

required
object <= 50 properties

Whole-object replacement; use an empty object to clear.

Responses

Request samples

Content type
application/json
{
  • "label": "Taylor Reed",
  • "reference": "EMP-1042",
  • "status": "inactive",
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "id": "rcp_01k2p7m4sd6t8v0x3y5z9a1bcf",
  • "customer_id": "cus_01jm0defbbct46vh2ev5dkkhej",
  • "label": "Taylor Reed",
  • "reference": "EMP-1042",
  • "association_status": "linked",
  • "status": "active",
  • "capabilities": {
    },
  • "metadata": {
    },
  • "created_at": "2026-07-31T09:05:00Z",
  • "updated_at": "2026-07-31T09:05:00Z"
}

Remove a recipient

Required scope: recipients:write.

Customer eligibility: authenticated business Customer only.

Soft-remove a linked or pending Recipient from this business's roster by recipient_id.

  • The recipient becomes removed and can_receive_transfers becomes false.
  • It remains available through direct retrieval and GET .../recipients?status=removed.
  • Unfiltered recipient lists exclude it.
  • Re-adding the same resolved Customer restores its current roster resource as a new relationship epoch.

Removing a Recipient cancels future pending resolution and does not affect a linked Pocket Customer or payment history.

Authorizations:
bearerAuth
path Parameters
business_customer_id
required
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: cus_01j8ma3wv3mepwabfxxs0yc395

The authenticated business Customer whose recipient roster the API manages. An individual Customer returns 403. Another Customer returns 404.

recipient_id
required
string^rcp_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: rcp_01k2p7m4sd6t8v0x3y5z9a1bcf

The Recipient (rcp_…) owned by this business Customer.

Responses

Response samples

Content type
application/json
Example
{
  • "code": "invalid_argument",
  • "message": "The request is invalid.",
  • "details": {
    }
}

Transactions

Money movement visible to the authenticated Customer. Each transaction is that Customer's single view of one txn_… and is either outbound (transfer) or inbound (deposit).

List transactions

Required scope: transactions:read.

List money-movement activity for the authenticated Customer. Recipient Customers' private activity is never included.

Narrow results with customer_id, kind, method, status, amount, reference, created date, or settled date.

When supplied, customer_id must identify the authenticated Customer.

Results are ordered by creation time and Transaction ID. Use order to return the oldest or newest Transactions first.

Each item is a transaction (txn_…) seen by the authenticated Customer:

  • Each id appears at most once. The API removes duplicates before ordering and pagination.
  • Use kind and id to fetch a transfer or deposit object when one exists.

An accepted internal transfer creates the source and destination Customer views at once:

  • The source entry is kind=transfer and starts pending.
  • The destination entry is kind=deposit and starts pending.
  • Both become settled, failed, or voided together. Each Customer can read only its own view.

A rejected transfer request creates no activity entry.

details carries method-specific facts and may gain fields before settlement. Events are references, not snapshots. Fetch the transaction for its current details.

If you sent money to a customer, your feed shows your transfer and its status, not the customer's resulting balance or unrelated activity. The feed excludes verification microdeposits, declined card authorizations, and Pocket-internal treasury operations.

The V1 feed does not model post-settlement returns or reversals. A future return will be a new balance-moving entry, not a change to an already settled status.

Authorizations:
bearerAuth
query Parameters
customer_id
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: customer_id=cus_01j8ma3wv3mepwabfxxs0yc395

Select the authenticated Customer's view.

  • Malformed or wrong-prefix value: 400. param is customer_id.
  • Another Customer returns privacy-preserving 404.
  • No matching activity returns an empty page.
kind
string (TransactionKind)
Enum: "transfer" "deposit"
Example: kind=deposit

Only transfers (outbound) or only deposits (inbound).

method
Array of strings (Method)
Items Enum: "internal" "ach" "wire" "onchain" "ibft" "swift" "faster_payments" "payment_link" "card"
Example: method=ach&method=wire

Filter transactions by method. Repeat the parameter to match more than one (e.g. method=ach&method=wire).

status
string (TransactionStatus)
Enum: "pending" "settled" "failed" "voided"

pending (accepted, not yet settled), settled (posted to the balance), failed, or voided. Pocket assigns voided. It does not mean that the caller canceled the transaction.

amount_min
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_min=100.00

Minimum amount (inclusive), as a decimal string in major units, e.g. 100.00.

amount_max
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_max=100.00

Maximum amount (inclusive), as a decimal string in major units, e.g. 100.00.

reference
string <= 255 characters

Exact match on your opaque reference for the object. Not unique. May match more than one object, and results are paginated.

created_after
string <date-time>
Example: created_after=2026-07-31T09:00:00Z

Only items created at/after this time (inclusive).

created_before
string <date-time>
Example: created_before=2026-07-31T09:00:00Z

Only items created at/before this time (inclusive).

settled_after
string <date-time>
Example: settled_after=2026-07-31T09:00:00Z

Only items settled at/after this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

settled_before
string <date-time>
Example: settled_before=2026-07-31T09:00:00Z

Only items settled at/before this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

order
string
Default: "desc"
Enum: "asc" "desc"

Sort by creation time. desc returns newest first; asc returns oldest first. IDs break ties in the same direction.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Retrieve a transaction

Required scope: transactions:read.

Fetch one transaction entry by ID, e.g. /v1/transactions/txn_….

The endpoint returns the authenticated Customer's view. A transaction that is not visible to that Customer returns 404.

Authorizations:
bearerAuth
path Parameters
transaction_id
required
string^txn_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: txn_01jjftqbz0n1vzey0pqrq3qmnn

Responses

Response samples

Content type
application/json
{
  • "id": "txn_01jjftqbz0n1vzey0pqrq3qmnn",
  • "customer_id": "cus_01j8ma3wv3mepwabfxxs0yc395",
  • "kind": "deposit",
  • "method": "ach",
  • "source": null,
  • "destination": {
    },
  • "amount": "2500.00",
  • "currency": "USD",
  • "status": "settled",
  • "details": {
    },
  • "created_at": "2026-07-30T14:10:00Z",
  • "settled_at": "2026-07-31T09:00:00Z"
}

Transfers

Money leaving the authenticated Customer's balance. V1 creates internal Customer-to-Customer transfers. Transfer reads also expose supported outbound activity already processed by Pocket.

List transfers

Required scope: transfers:read.

Outbound money movements from the authenticated Customer.

  • The list includes every method that produces a transfer object.
  • Card activity is feed-only. See Transactions.

Narrow results with method, source_customer_id, destination_id, status, amount, reference, created date, or settled date.

When supplied, source_customer_id must identify the authenticated Customer.

destination_id is a counterparty filter. It may identify a Pocket Customer or an external instrument already visible on one of the authenticated Customer's transfers. Historical activity without an instrument ID is not matched by this filter.

Results are ordered by creation time and Transfer ID. Use order to return the oldest or newest Transfers first.

Authorizations:
bearerAuth
query Parameters
method
Array of strings (TransferMethod)
Items Enum: "internal" "ach" "wire" "onchain" "ibft"
Example: method=ach&method=wire

Filter transfers by method. Repeat the parameter to match more than one (e.g. method=ach&method=wire). A method that cannot produce a Transfer returns 400 invalid_request with param=method rather than an empty result.

source_customer_id
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$

Filter by the authenticated Customer. Another Customer returns privacy-preserving 404.

destination_id
string^(?:cus_|epi_)[0-7][0-9abcdefghjkmnpqrstvwxyz...

Filter by a Pocket Customer for an internal transfer, or an external instrument for an ACH, wire, IBFT, or onchain transfer. A Customer destination may be a counterparty outside the authenticated Customer's ownership boundary.

  • Malformed or wrong-prefix value: 400. param is destination_id.
  • No matching visible transfers: empty page, without disclosing whether it exists.
status
string (TransferStatus)
Enum: "pending" "settled" "failed" "voided"

pending (accepted, not yet settled), settled (posted to the balance), failed, or voided. Pocket assigns voided to an accepted transfer that will not settle. There is no public cancel or void endpoint.

amount_min
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_min=100.00

Minimum amount (inclusive), as a decimal string in major units, e.g. 100.00.

amount_max
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_max=100.00

Maximum amount (inclusive), as a decimal string in major units, e.g. 100.00.

reference
string <= 255 characters

Exact match on your opaque reference for the object. Not unique. May match more than one object, and results are paginated.

created_after
string <date-time>
Example: created_after=2026-07-31T09:00:00Z

Only items created at/after this time (inclusive).

created_before
string <date-time>
Example: created_before=2026-07-31T09:00:00Z

Only items created at/before this time (inclusive).

settled_after
string <date-time>
Example: settled_after=2026-07-31T09:00:00Z

Only items settled at/after this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

settled_before
string <date-time>
Example: settled_before=2026-07-31T09:00:00Z

Only items settled at/before this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

order
string
Default: "desc"
Enum: "asc" "desc"

Sort by creation time. desc returns newest first; asc returns oldest first. IDs break ties in the same direction.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Create an internal transfer

Required scope: transfers:write.

Move funds from the Customer in source.customer_id to the Pocket Customer in destination.customer_id. The source must be the authenticated Customer. The destination Customer's private balance and activity remain hidden.

At acceptance

  • Source: kind is transfer, method is internal, and status is pending.
  • Destination: kind is deposit, method is internal, and status is pending.
  • Each Customer can immediately read its own view.
  • Source available decreases and reserved increases.

At settlement

Both views become settled. The source reservation posts out. Pocket credits the destination settled and available amounts.

On failure or voiding

Both views remain visible with the terminal status. Pocket releases the source reservation and never credits the destination.

If the API rejects a request before it creates a txn_…, it produces no transfer, deposit, or transaction resource.

A source Customer that cannot send returns 403 forbidden. A destination Customer that cannot receive the transfer returns 403 recipient_not_payable. The response does not reveal the private Customer-state reason.

Authorizations:
bearerAuth
Request Body schema: application/json
required
idempotency_key
required
string [ 1 .. 255 ] characters .*\S.*

Required non-blank value reserved for idempotency. V1 validates the field but does not yet guarantee replay or duplicate suppression for this operation.

required
object (TransferSource)

The Customer whose available balance funds the transfer. It must be the authenticated Customer. The request's currency or source_currency must equal that Customer balance's currency. A mismatch returns 400 invalid_request with param set to that currency field.

required
object (CustomerReference)

A Pocket customer reference. A destination may be an individual or a business unless the operation says otherwise. Using a customer as a transfer destination does not grant read or administrative access to it.

amount
required
string (WriteAmount) <= 19 characters ^(?:0\.(?:0[1-9]|[1-9][0-9]?)|[1-9][0-9]{0,15...

A positive amount to move, expressed as a JSON decimal string in major units. For example, "100.00" means 100 USD.

  • The value must be greater than zero.
  • USD supports 1–16 integer digits and at most two fractional digits.
  • The maximum value is "9999999999999999.99".
  • Signs, commas, whitespace, scientific notation, leading-dot forms, trailing-dot forms, and unnecessary leading zeros are invalid.
  • The complete value may contain at most 19 characters.
  • For Batch idempotency, decimal-equivalent forms such as "1", "1.0", and "1.00" are treated as the same amount.

An invalid, non-positive or overflowing amount returns 400 invalid_request. param names the request field, such as amount, source_amount or items[n].amount. The request creates or changes nothing. Other Customer and rail limits may impose a lower maximum.

currency
required
string (Currency)
Value: "USD"

Public settlement currency debited from or credited to a Customer balance.

  • USD is the only value emitted in V1.
  • Clients must preserve and tolerate future values.
  • Cross-currency payouts may define separate destination-currency and foreign exchange (FX) fields.
reference
string <= 255 characters

Your private external reference for this transfer (e.g. a pay-run or employee ID). Optional, not unique. Filter by it. Counterparties do not see it.

memo
string <= 100 characters

Payment note carried on the movement and visible to the destination customer when the method supports a note. Internal transfer memos can be up to 100 characters. The API rejects longer values with 400 (param is memo) and never truncates them.

Responses

Request samples

Content type
application/json
{
  • "idempotency_key": "d9f80740-7f8e-4f16-b5cc-4fd5bf7d3b21",
  • "source": {
    },
  • "destination": {
    },
  • "amount": "100.00",
  • "currency": "USD",
  • "reference": "payrun-2026-07",
  • "memo": "July salary"
}

Response samples

Content type
application/json
{
  • "id": "txn_01k0d2f6h8j4m7n9p3q5r1s0vw",
  • "method": "internal",
  • "reference": "payrun-2026-07",
  • "memo": "July salary",
  • "source": {
    },
  • "destination": {
    },
  • "batch_id": null,
  • "amount": "100.00",
  • "currency": "USD",
  • "status": "pending",
  • "failure_code": null,
  • "failure_message": null,
  • "transitioned_at": {
    },
  • "created_at": "2026-07-31T11:00:00Z",
  • "updated_at": "2026-07-31T11:00:00Z"
}

Retrieve a transfer

Required scope: transfers:read.

Fetch one transfer by ID, e.g. /v1/transfers/txn_….

This endpoint returns the outbound side when its source Customer is the authenticated Customer. Otherwise it returns 404.

For an internal movement, the same txn_… may also be retrievable from GET /v1/deposits/{deposit_id} by the destination Customer. The transfer is retrievable as soon as its txn_… exists and remains retrievable through its terminal status.

Authorizations:
bearerAuth
path Parameters
transfer_id
required
string^txn_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: txn_01k0d2f6h8j4m7n9p3q5r1s0vw

Responses

Response samples

Content type
application/json
{
  • "id": "txn_01k0d2f6h8j4m7n9p3q5r1s0vw",
  • "method": "internal",
  • "reference": "payrun-2026-07",
  • "memo": "July salary",
  • "source": {
    },
  • "destination": {
    },
  • "batch_id": null,
  • "amount": "100.00",
  • "currency": "USD",
  • "status": "pending",
  • "failure_code": null,
  • "failure_message": null,
  • "transitioned_at": {
    },
  • "created_at": "2026-07-31T11:00:00Z",
  • "updated_at": "2026-07-31T11:00:00Z"
}

Deposits

Money arriving in the authenticated Customer's balance. Deposits are read-only: Pocket creates them from incoming payments and the destination side of an internal transfer.

List deposits

Required scope: deposits:read.

Inbound money movements into the authenticated Customer's balance.

  • The list includes every method that produces a deposit object.
  • Card refunds are feed-only. See Transactions.
  • Deposits are read-only: you never create one.

Narrow results with method, customer_id, status, amount, reference, created date, or settled date.

A transfer appears in the destination Customer's results as soon as its txn_… identifier exists.

For an internal movement:

  • The deposit appears immediately as pending.
  • It does not affect destination balances until settlement.
  • A later failure or void leaves the deposit visible with that terminal status.

When supplied, customer_id must identify the authenticated Customer.

Results are ordered by creation time and Deposit ID. Use order to return the oldest or newest Deposits first.

Authorizations:
bearerAuth
query Parameters
method
Array of strings (DepositMethod)
Items Enum: "internal" "ach" "wire" "onchain" "swift" "faster_payments" "payment_link"
Example: method=ach&method=wire

Filter deposits by method. Repeat the parameter to match more than one (e.g. method=ach&method=wire). A method that cannot produce a Deposit returns 400 invalid_request with param=method rather than an empty result.

customer_id
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: customer_id=cus_01j8ma3wv3mepwabfxxs0yc395

Select the authenticated Customer's view.

  • Malformed or wrong-prefix value: 400. param is customer_id.
  • Another Customer returns privacy-preserving 404.
  • No matching activity returns an empty page.
status
string (TransactionStatus)
Enum: "pending" "settled" "failed" "voided"

pending (accepted, not yet settled), settled (posted to the balance), failed, or voided. Pocket assigns voided. It does not mean that the caller canceled the transaction.

amount_min
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_min=100.00

Minimum amount (inclusive), as a decimal string in major units, e.g. 100.00.

amount_max
string (MoneyAmount) <= 19 characters ^(?:0(?:\.[0-9]{1,2})?|[1-9][0-9]{0,15}(?:\.[...
Example: amount_max=100.00

Maximum amount (inclusive), as a decimal string in major units, e.g. 100.00.

reference
string <= 255 characters

Exact match on your opaque reference for the object. Not unique. May match more than one object, and results are paginated.

created_after
string <date-time>
Example: created_after=2026-07-31T09:00:00Z

Only items created at/after this time (inclusive).

created_before
string <date-time>
Example: created_before=2026-07-31T09:00:00Z

Only items created at/before this time (inclusive).

settled_after
string <date-time>
Example: settled_after=2026-07-31T09:00:00Z

Only items settled at/after this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

settled_before
string <date-time>
Example: settled_before=2026-07-31T09:00:00Z

Only items settled at/before this time (inclusive). This filter excludes pending, failed, and voided items because they have no settlement time.

order
string
Default: "desc"
Enum: "asc" "desc"

Sort by creation time. desc returns newest first; asc returns oldest first. IDs break ties in the same direction.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Retrieve a deposit

Required scope: deposits:read.

Fetch one deposit by ID, e.g. /v1/deposits/txn_….

This endpoint returns the inbound side when its destination Customer is the authenticated Customer. Otherwise it returns 404.

For an internal movement:

  • The same txn_… may resolve at GET /v1/transfers/{transfer_id} for the source Customer.
  • The deposit is retrievable immediately after transaction creation, including while pending.
  • It remains retrievable after becoming failed or voided.
Authorizations:
bearerAuth
path Parameters
deposit_id
required
string^txn_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: txn_01jjftqbz0n1vzey0pqrq3qmnn

Responses

Response samples

Content type
application/json
{
  • "id": "txn_01jjftqbz0n1vzey0pqrq3qmnn",
  • "method": "ach",
  • "customer_id": "cus_01j8ma3wv3mepwabfxxs0yc395",
  • "source": null,
  • "destination": {
    },
  • "reference": null,
  • "memo": null,
  • "amount": "2500.00",
  • "currency": "USD",
  • "status": "settled",
  • "details": {
    },
  • "created_at": "2026-07-30T14:10:00Z",
  • "settled_at": "2026-07-31T09:00:00Z",
  • "updated_at": "2026-07-31T09:00:00Z"
}

Batch Transfers

An asynchronous group of internal transfers from one authenticated business Customer to destination Customers. Every item has its own status and may fail without changing the result of another item.

Create a batch of transfers

Required scopes: batches:write and transfers:write.

Customer eligibility: authenticated business Customer only.

Submit internal transfers from the Customer in source.customer_id asynchronously. The source must be the authenticated business Customer. Acceptance does not move or reserve money. An ineligible source returns 403, and the API creates no batch.

Every item's currency must equal the source Customer balance's currency. A mismatch returns 400 invalid_request with param=items[n].currency, where n is the zero-based item index.

  • Each item checks available balance only when it runs.
  • Item processing order is not guaranteed.

Recipient policy pre-check

recipient_policy defaults to any_customer. Set it to recipients_only to check the complete batch against the authenticated Customer's recipient list before acceptance:

  • The authenticated Customer must have a linked Recipient whose customer_id equals every destination.customer_id.
  • Every matched recipient must currently have capabilities.can_receive_transfers set to true.

This check runs after ordinary validation, including duplicate item_id validation. If any item fails, one 400 recipient_policy_failed response lists all failures in request order. The request creates nothing and leaves the idempotency key unbound. Correct it and retry with a new key.

The recipient check is not repeated during item processing. Ordinary transfer rules still apply.

Track every submitted line with GET /v1/batches/{batch_id}/items.

  • A failure before transaction creation has transfer_id: null.
  • Once a txn_… exists, transfer_id identifies it through settlement, failure or voiding.
  • Insufficient funds at execution produces failure_code: insufficient_funds.
  • Retry failed lines in a new batch. item_id does not deduplicate across batches. resubmitting a settled line can pay twice.

Duplicate item ids

Every item_id must be unique within items.

  • Comparison is exact and case-sensitive.
  • Pocket does not trim, case-fold, or normalize the value.
  • Other line fields do not affect duplicate detection.
  • reference and idempotency_key do not identify batch lines.

Pocket reports the first repeated value. The request returns 400 invalid_request, with param set to the second occurrence (items[n].item_id). The index is zero-based.

The request creates nothing and leaves the idempotency key unbound. Correct it and retry with a new key.

You cannot cancel a batch after acceptance.

Authorizations:
bearerAuth
Request Body schema: application/json
required
idempotency_key
required
string [ 1 .. 255 ] characters .*\S.*

Binds this Batch create request for 24 hours. During that period, an unchanged retry returns the existing Batch and a changed request returns 409. At or after 24 hours, the key is treated as new.

required
object (TransferSource)

The Customer whose available balance funds the transfer. It must be the authenticated Customer. The request's currency or source_currency must equal that Customer balance's currency. A mismatch returns 400 invalid_request with param set to that currency field.

recipient_policy
string (BatchRecipientPolicy)
Default: "any_customer"
Enum: "any_customer" "recipients_only"

One-time destination pre-check applied before Pocket accepts a batch.

  • any_customer: skip the recipient pre-check. Each destination may be any valid Pocket customer.
  • recipients_only: every destination must meet all these conditions:
    • The authenticated Customer has a linked Recipient whose customer_id equals this destination.
    • Its current capabilities.can_receive_transfers value is true.

The policy is not evaluated again after acceptance or as individual transfers execute. Omitting the field and sending any_customer are equivalent for Batch idempotency.

required
Array of objects (BatchTransferItem) [ 1 .. 4096 ] items

Each item_id must be unique in the array. Pocket enforces this at runtime because OpenAPI 3.0 uniqueItems compares whole objects rather than one field.

reference
string <= 255 characters

Your external ID for this batch (e.g. a pay-run ID). Optional, filterable.

object (Metadata) <= 50 properties

Up to 50 caller-defined string key/value pairs. An empty object is valid.

Keys

  • 1–64 Unicode characters.
  • Compared exactly as supplied.
  • Not trimmed, case-folded, or Unicode-normalized.
  • Any Unicode character except NUL (U+0000).

OpenAPI 3.0 cannot express the key-length limit for arbitrary properties, so Pocket enforces it at runtime. An invalid key returns 400 invalid_request with param=metadata. The key is not echoed.

Values

  • String values only.
  • Empty values are allowed.
  • Maximum 256 Unicode characters.
  • NUL (U+0000) is not allowed.
  • Preserved exactly as supplied, without trimming or Unicode normalization.

An overlong value returns 400 invalid_request. param is metadata.<key> when the key is valid, or metadata when the key is invalid. The value is never echoed.

Privacy

The API shows metadata only in the Customer view where the caller set it. The API does not share metadata with money-movement counterparties. Use it for opaque business identifiers and non-sensitive labels only.

Do not include:

  • Government identity values.
  • Bank-account, routing, or payment-card details.
  • Passwords, secrets, access tokens, or credentials.
  • KYC documents.
  • Biometric or health information.
  • Names, email addresses, or phone numbers when a dedicated field exists.

Pocket may reject metadata that appears sensitive, but the caller remains responsible for the data it supplies.

Responses

Request samples

Content type
application/json
{
  • "idempotency_key": "a15e4ae4-52f3-460c-9c1c-5f6b7b90cc44",
  • "source": {
    },
  • "recipient_policy": "recipients_only",
  • "items": [
    ],
  • "reference": "northwind-payroll-2026-07",
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "id": "batch_01j5gr81vpavng9emxaepf2be3",
  • "reference": "northwind-payroll-2026-07",
  • "source": {
    },
  • "recipient_policy": "recipients_only",
  • "status": "pending",
  • "item_counts": {
    },
  • "amount_totals": [
    ],
  • "metadata": {
    },
  • "created_at": "2026-07-31T10:00:00Z",
  • "finalized_at": null
}

List batches

Required scope: batches:read.

Customer eligibility: authenticated business Customer only.

List batches submitted by the authenticated Customer.

When supplied, source_customer_id must identify the authenticated Customer. Results are ordered by creation time and Batch ID. Use order to return the oldest or newest Batches first.

Authorizations:
bearerAuth
query Parameters
source_customer_id
string^cus_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$

Filter by the authenticated Customer. Another Customer returns privacy-preserving 404.

status
string (BatchStatus)
Enum: "pending" "processing" "completed" "partially_completed" "failed"

Summary status derived from the batch item counts:

  • pending: item_counts.pending == item_counts.total.
  • processing: 0 < item_counts.pending < item_counts.total.
  • completed: item_counts.settled == item_counts.total.
  • partially_completed: item_counts.pending == 0 and some, but not all, items settled.
  • failed: terminal with zero settled items. Items may be failed or voided.

The counts are the source of truth for reconciliation and always satisfy item_counts.pending + item_counts.settled + item_counts.failed + item_counts.voided == item_counts.total.

created_after
string <date-time>
Example: created_after=2026-07-31T09:00:00Z

Only items created at/after this time (inclusive).

created_before
string <date-time>
Example: created_before=2026-07-31T09:00:00Z

Only items created at/before this time (inclusive).

reference
string <= 255 characters

Exact match on your opaque reference for the object. Not unique. May match more than one object, and results are paginated.

order
string
Default: "desc"
Enum: "asc" "desc"

Sort by creation time. desc returns newest first; asc returns oldest first. IDs break ties in the same direction.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Retrieve a batch

Required scope: batches:read.

Customer eligibility: authenticated business Customer only.

Retrieve a batch by ID. Use its item counts and amount totals to track progress.

Authorizations:
bearerAuth
path Parameters
batch_id
required
string^batch_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
Example: batch_01j5gr81vpavng9emxaepf2be3

Responses

Response samples

Content type
application/json
{
  • "id": "batch_01j5gr81vpavng9emxaepf2be3",
  • "reference": "northwind-payroll-2026-07",
  • "source": {
    },
  • "recipient_policy": "recipients_only",
  • "status": "pending",
  • "item_counts": {
    },
  • "amount_totals": [
    ],
  • "metadata": {
    },
  • "created_at": "2026-07-31T10:00:00Z",
  • "finalized_at": null
}

List a batch's items

Required scope: batches:read.

Customer eligibility: authenticated business Customer only.

List every submitted item in the batch, including items that failed before creating a transfer.

Use item_id to reconcile the response with the line you submitted. When an item creates a transfer, transfer_id links to the resulting txn_…. Otherwise transfer_id is null and failure_code explains the failure.

Narrow with item_id, status, or reference.

To retry failures, submit the failed lines in a new batch. A new batch creates new transfers. item_id does not deduplicate across batches, so resubmitting a settled line can pay the same customer twice.

The API orders results by (created_at ASC, item_id ASC).

Authorizations:
bearerAuth
path Parameters
batch_id
required
string^batch_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
query Parameters
item_id
string [ 1 .. 255 ] characters .*\S.*

Only the batch item with this caller-supplied ID. Unique within the batch.

status
string (BatchItemStatus)
Enum: "pending" "settled" "failed" "voided"

Lifecycle of one submitted batch item. When a transfer exists, this mirrors the transfer status. Pocket assigns voided to an item that will not settle and is not a failure. failure_code is absent.

reference
string <= 255 characters

Exact match on your opaque reference for the object. Not unique. May match more than one object, and results are paginated.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

List a batch's transfers

Required scopes: batches:read and transfers:read.

Customer eligibility: authenticated business Customer only.

Only items that produced a transfer appear here. Every submitted item appears in GET /v1/batches/{batch_id}/items. An item that fails before transfer creation, such as for insufficient funds when it runs, has transfer_id: null. The API orders results by (created_at ASC, id ASC).

Authorizations:
bearerAuth
path Parameters
batch_id
required
string^batch_[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}$
query Parameters
status
string (TransferStatus)
Enum: "pending" "settled" "failed" "voided"

pending (accepted, not yet settled), settled (posted to the balance), failed, or voided. Pocket assigns voided to an accepted transfer that will not settle. There is no public cancel or void endpoint.

cursor
string <= 8192 characters

Opaque cursor (next_cursor from a prior page). Re-supply the same filters. A mismatch or invalid cursor returns 400.

limit
integer [ 1 .. 100 ]
Default: 25

Responses

Response samples

Content type
application/json
{
  • "has_more": true,
  • "next_cursor": "string",
  • "data": [
    ]
}

Changelog

0.4.0

Customer-scoped V1

  • Replaced the Account-scoped API with a smaller Customer-scoped API for balances, Recipients, Transactions, Transfers, Deposits and Batches.
  • Scoped balances and activity to the Customer represented by the API key. 0.4.0 returns that Customer's single USD balance.
  • Changed Transfer and Batch sources to use the authenticated Customer's ID and kept destination Customer IDs separate.
  • Limited Transfer creation to internal Customer-to-Customer transfers.
  • Added ascending and descending creation-time ordering to Recipient, Transaction, Transfer, Deposit and Batch lists.

Recipients

  • Added stable Recipient IDs (rcp_…). Retrieve, replace and remove operations now address the Recipient rather than its linked Customer.
  • Changed Recipient replacement from PATCH to PUT. The request supplies the complete mutable state: label, reference, status and metadata.
  • Added exact paytag matching during Recipient creation, alongside exact Customer ID, email and phone matching. Removed government-ID lookup and the separate Recipient search operation.
  • Removed creation of unmatched Customers and pending Recipients. An incomplete or conflicting match returns 404 recipient_not_found and creates nothing.
  • Recipient responses contain the stable Recipient ID, linked Customer ID when available, business-owned label, reference and metadata, association and relationship status, transfer capability, and timestamps. Contact details and Customer onboarding state are not returned.

Requests and retries

  • Recipient creation and Batch creation are idempotent for 24 hours. Recipient replacement has the same guarantee when an idempotency_key is supplied. Other operations may accept an idempotency key, but V1 does not guarantee replay or duplicate suppression for them.
  • Bound Recipient list cursors to the owning Customer and normalized filters. 0.4.0 does not define a cursor lifetime. An invalid or mismatched cursor returns 400, and the caller can restart from the first page.
  • Changed all errors to the { code, message, details } envelope. Recipient operations document more specific error detail schemas and HTTP responses. Retry-After is optional on rate-limit responses.
  • Removed unsupported request-body size promises and the corresponding 413 responses.
  • Rejected the NUL character in Recipient idempotency keys, labels, references, metadata and text filters.

Changes since 0.2.0

0.2.0 0.4.0
Account-scoped balances and activity using account_id Customer-scoped balance and activity using customer_id. Accounts are not included.
Internal, ACH, wire, onchain and IBFT Transfer creation Internal Customer-to-Customer Transfer creation only.
Recipients addressed through their linked Customer ID and updated with PATCH Stable rcp_… Recipient IDs and complete replacement with PUT. Responses no longer include contact or onboarding fields.
Instruments, funding rules, FX quotes, events and webhooks These operations are not included.
Flat { code, message, param, request_id } errors { code, message, details } errors.
At least 24 hours of idempotent replay for every operation that accepted a key 24 hours of replay for Recipient creation, Recipient replacement when a key is supplied, and Batch creation. Other operations do not guarantee replay or duplicate suppression.

0.2.0

  • Renamed the specification from Pocket Money API to Pocket Money - Relay API and moved its base URL from api.pocketmoney.host to api.relay.pocketmoney.global.
  • Replaced API-created business subcustomers (cus_…) with Customer-owned Accounts (acc_…) as directly addressable funds containers. Removed the public Customer hierarchy and subcustomer management operations.
  • Changed balances, transactions, deposits, Transfer sources, Batch sources and funding rules to address Accounts. Added same-Customer Account-to-Account transfers and default receiving Account selection when an internal Transfer addresses a Customer.
  • Replaced business-member resources with Customer-to-Customer Recipients. Added Recipient endpoints, scopes and the recipients_only Batch policy.
  • Added Customer-owned external instruments (epi_…) for bank accounts and wallet addresses, including Customer-held and third-party bank holders.
  • Added outbound ACH and wire Transfers. The 0.1.0 specification supported only internal Transfer creation.
  • Added onchain Transfers to reusable wallet-address instruments and exposed incoming onchain Deposits.
  • Added FX quotes and USD-to-PKR IBFT Transfers, including supported-bank and purpose-code lists, Transfer-level purpose codes and third-party PKR destinations.

Migrating from 0.1.0

Regenerate typed clients from the 0.2.0 specification before switching endpoints. API keys remain associated with one Customer. Update integrations that used the 0.1.0 subcustomer model as follows:

0.1.0 integration Required 0.2.0 change
Create, list, retrieve or update subcustomers through /v1/customers Use /v1/accounts and /v1/accounts/{account_id}. Store the returned acc_… ID. Do not derive it from or substitute a previous cus_… ID.
Address balances and money activity by customer_id Use account_id. This includes source.account_id, Account-relative balance, Transaction and Deposit fields, and the account_id or source_account_id list filters. A Customer destination for an internal Transfer still uses destination.customer_id.
Read /v1/customers/{customer_id}/balances or filter balances by parent_customer_id For one Account, use /v1/accounts/{account_id}/balance. For a list, use /v1/accounts and /v1/balances.
Manage funding rules below /v1/customers/{customer_id}/funding_rules with destination_customer_id Use /v1/accounts/{account_id}/funding_rules. Supply destination_account_id. Responses use source_account_id and destination_account_id.
Use member endpoints, members:* scopes or recipient_policy=payable_members Use Recipient endpoints, recipients:* scopes and recipient_policy=recipients_only.
Submit Batches with source.customer_id Submit the source Account as source.account_id. Batch-item Customer destinations remain destination.customer_id.
Persist 0.1.0 list cursors or handle member event resource references Restart pagination without the saved cursor. Handle recipient and new Account-related resource references, and continue accepting unknown event types and resource identifiers.
Grant customers:read or customers:write Grant accounts:read or accounts:write. Grant the new instruments:* scopes only when using instrument operations.

Do not mechanically replace every customer_id. Customer destinations, instrument ownership paths and the top-level Event.customer_id continue to use cus_… identifiers.

0.1.0

  • Introduced the initial API specification for Customer balances and activity, internal Transfers, Deposits, Batch transfers, funding rules, members, events and webhook endpoints.
  • Used API-created business subcustomers (cus_…) as separate money holders and Transfer or Batch sources.