> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pontisglobe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# /api/v1/beneficiaries/listBeneficiaries

> List your saved recipients, filtered and cursor-paginated.

<Warning>
  The fields above are what you **encrypt**, not what goes on the wire. The body is always
  `{ "data": "<aes-256-gcm ciphertext>" }` — see [Authentication](/authentication).
</Warning>

Every field is optional. Sending `{}` lists all of them.

## Pagination

`next_cursor` is `null` on the last page. Pass it back as `cursor` to fetch the next one — do not
construct cursors yourself, and do not assume they stay valid indefinitely.

<Warning>
  `recipient_details` is **masked** on every item, the same as a single read. A list is not a way to
  export what you stored.
</Warning>

## Example request

<Info>
  The snippets assume you have already encrypted the body and signed the request — see the
  [Quickstart](/quickstart) for the full helper in Node and Python.
</Info>

<CodeGroup>
  ```js Node theme={null}
  // One page
  const page = await call(
    '/api/v1/beneficiaries/listBeneficiaries',
    { country_code: 'NG', limit: 50 },
    jwt,
  )

  // Every page
  let cursor = undefined
  do {
    const res = await call('/api/v1/beneficiaries/listBeneficiaries', { limit: 100, cursor }, jwt)
    handle(res.data.items)
    cursor = res.data.next_cursor
  } while (cursor)
  ```

  ```python Python theme={null}
  cursor = None
  while True:
      status, body = call('/api/v1/beneficiaries/listBeneficiaries', {
          'limit': 100,
          **({'cursor': cursor} if cursor else {}),
      }, jwt)
      handle(body['data']['items'])
      cursor = body['data']['next_cursor']
      if not cursor:
          break
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.pontisglobe.com/api/v1/beneficiaries/listBeneficiaries" \
    -H "content-type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "x-timestamp: 1748023400" \
    -H "x-signature: 2f8a9b…" \
    -H "authorization: Bearer YOUR_JWT" \
    -d '{"data":"<encrypted blob>"}'
  ```
</CodeGroup>

See [Beneficiaries](/beneficiaries) for how saving and reusing recipients fits together, and
[Errors](/errors) for the envelope shape shared by every endpoint.


## OpenAPI

````yaml openapi.yaml POST /api/v1/beneficiaries/listBeneficiaries
openapi: 3.1.0
info:
  title: PontisGlobe API
  version: 1.0.0
  summary: Accept stablecoin payments and send cross-border payouts.
  description: |
    Two products on one balance.

    **Global Collections** — accept USDT and USDC through a hosted checkout.
    **Global Payouts** — pay out in local currency across 50+ countries.

    Every endpoint is `POST`, authenticated with an API key and an HMAC-SHA256
    signature, and carries an AES-256-GCM encrypted body. Payout and beneficiary
    endpoints additionally require a short-lived JWT obtained from
    `/api/v1/user/login`.

    ## Request bodies are encrypted

    The fields documented on each endpoint are what you **encrypt**, not what
    goes on the wire. Every request body is a single envelope:

    ```json
    { "data": "<base64 AES-256-GCM ciphertext>" }
    ```

    So a client that posts the documented JSON directly will be rejected before
    validation. Read
    [Authentication](https://docs.pontisglobe.com/authentication) and build the
    envelope first — it is about fifteen lines of helper code, and the docs give
    it in Node and Python.
  contact:
    name: PontisGlobe Support
    url: https://www.pontisglobe.com/contact
servers:
  - url: https://api.pontisglobe.com
    description: Live. Real money.
  - url: https://sandbox.pontisglobe.com
    description: |
      Sandbox. Deterministic outcomes driven by the trailing cents of
      `source_amount` — see https://docs.pontisglobe.com/sandbox.
security:
  - ApiKeyAuth: []
tags:
  - name: Authentication
    description: Exchange credentials for a short-lived JWT.
  - name: Payouts
    description: Send money to bank accounts and mobile money in 50+ countries.
  - name: Beneficiaries
    description: Save a recipient once, then pay them by id.
  - name: Payins
    description: Accept stablecoin payments through a hosted checkout.
paths:
  /api/v1/beneficiaries/listBeneficiaries:
    post:
      tags:
        - Beneficiaries
      summary: List your beneficiaries
      description: Cursor-paginated. Sensitive values are masked.
      operationId: listBeneficiaries
      parameters:
        - $ref: '#/components/parameters/TimestampHeader'
        - $ref: '#/components/parameters/SignatureHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                country_code:
                  type: string
                  minLength: 2
                  maxLength: 2
                  example: NG
                currency_code:
                  type: string
                  minLength: 2
                  maxLength: 8
                  example: NGN
                cursor:
                  type: string
                  format: uuid
                  description: >
                    `next_cursor` from the previous page — it is the last

                    `beneficiary_id` of that page. Do not construct one
                    yourself.
                limit:
                  type: integer
                  minimum: 1
                  maximum: 100
                  default: 20
                  example: 50
      responses:
        '200':
          description: A page of beneficiaries.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                  data:
                    type: object
                    properties:
                      items:
                        type: array
                        items:
                          $ref: '#/components/schemas/Beneficiary'
                      next_cursor:
                        type:
                          - string
                          - 'null'
                        description: '`null` on the last page.'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
      security:
        - ApiKeyAuth: []
          BearerAuth: []
components:
  parameters:
    TimestampHeader:
      name: x-timestamp
      in: header
      required: true
      description: |
        Unix epoch **in seconds** — not milliseconds. Must be within ±5 minutes
        of our clock, which is what makes a captured request unusable later.
        Keep your client's clock NTP-synced.
      schema:
        type: integer
        format: int64
        example: 1748023400
    SignatureHeader:
      name: x-signature
      in: header
      required: true
      description: |
        HMAC-SHA256 over the signing string, hex encoded. The timestamp is part
        of what is signed, so a replayed body cannot be re-dated. See
        https://docs.pontisglobe.com/authentication for how it is built.
      schema:
        type: string
        example: 2f8a9b4c1d7e0a3f6b8c2d5e9f1a4b7c0d3e6f9a2b5c8d1e4f7a0b3c6d9e2f5a
  schemas:
    Beneficiary:
      type: object
      required:
        - beneficiary_id
        - status
        - country_code
        - currency_code
        - payment_method
        - recipient_name
        - recipient_details
        - created_at
      properties:
        beneficiary_id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - active
            - archived
        country_code:
          type: string
          example: NG
        currency_code:
          type: string
          example: NGN
        payment_method:
          type: string
          example: bank_local
        payment_network:
          type:
            - string
            - 'null'
          description: Mobile-money network, where the corridor requires one.
        recipient_name:
          type: string
        recipient_details:
          type: object
          additionalProperties: true
          description: |
            Per-corridor fields. **Sensitive values are masked on read** — an
            account number comes back partially redacted, so this object cannot
            be round-tripped straight into `updateBeneficiary`.
        nickname:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        last_used_at:
          type:
            - string
            - 'null'
          format: date-time
    Error:
      type: object
      required:
        - ok
        - request_id
        - error
      properties:
        ok:
          type: boolean
          enum:
            - false
        request_id:
          type: string
          format: uuid
          description: |
            Identifies this exact request in our logs. Quote it when contacting
            support — it is the fastest path to an answer.
          example: 8c1f4b2a-9d3e-4a71-b6c8-5e2f0a7d1934
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable, machine-readable. Branch on this, never on `message`.
              example: insufficient_funds
            message:
              type: string
              description: Human-readable. Wording may change without notice.
              example: 'Insufficient available balance. Available: 5.00 USDT'
  responses:
    BadRequest:
      description: >-
        `validation_error` — schema mismatch. Fix and retry; do not retry
        unchanged.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: >-
        `unauthorized` or `jwt_expired` — bad credentials or an expired JWT.
        Re-login.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: '`rate_limited` — back off and retry with a longer interval.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ServerError:
      description: '`internal_error` — contact support quoting `request_id`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Identifies your account. Issued from Developer Tools in the dashboard.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Short-lived token from `/api/v1/user/login`, bound to your account and
        mode. Expires in 900 seconds.

````