Payouts

Payouts move available balance to a financial account. You choose a destination, maximum amount, and earliest execution time; the payout response exposes its current status, public error details, linked balance transactions, and lifecycle timestamps.

Schedule, cancel, set destinations, enable automatic payouts, disable automatic payouts, enable FX, and disable FX support idempotency. A successful response can be replayed with the same idempotency key and request body for 24 hours. Lookup, settings, and page do not opt in to idempotent replay.

The Payout object

Optional payout fields are omitted until they have values. The public object does not include execution-attempt records or attempt counters.

Properties

  • amountobjectActual payout amount when known. Omitted before the amount is determined.Click or tap to expand
    • Name
      currency
      Type
      string
      Description
      Lowercase currency code.
    • Name
      value
      Type
      integer
      Description
      Amount in the smallest currency unit.
  • Name
    balance_transactions
    Type
    array
    Description

    Balance transaction IDs linked to the payout. Omitted until transactions are linked.

  • Name
    canceled_at
    Type
    timestamp
    Description

    When the payout was canceled. Omitted otherwise.

  • Name
    custom_data
    Type
    object
    Description

    Your string key-value metadata, when available.

  • Name
    destination_id
    Type
    string
    Description

    Financial account selected as the destination.

  • errorobjectPublic error details when payout execution fails. Omitted when no error is present.Click or tap to expand
    • Name
      cause
      Type
      string
      Description
      Underlying public cause.
    • Name
      message
      Type
      string
      Description
      Human-readable error message.
    • Name
      occurred_at
      Type
      timestamp
      Description
      When the error occurred.
    • Name
      type
      Type
      string
      Description
      Machine-readable error type.
  • Name
    execute_after
    Type
    timestamp
    Description

    Earliest time execution can begin.

  • Name
    executed_by
    Type
    string
    Description

    Actor that executed the payout, when available.

  • Name
    expected_at
    Type
    timestamp
    Description

    Expected completion time, when available.

  • Name
    failed_at
    Type
    timestamp
    Description

    When the payout entered its unsuccessful terminal state. Omitted otherwise.

  • Name
    id
    Type
    string
    Description

    Unique payout identifier.

  • Name
    initiated_at
    Type
    timestamp
    Description

    When the payout record was created.

  • Name
    initiated_by
    Type
    string
    Description

    Actor that initiated the payout, when available.

  • max_amountobjectMaximum authorized payout amount.Click or tap to expand
    • Name
      currency
      Type
      string
      Description
      Lowercase currency code.
    • Name
      value
      Type
      integer
      Description
      Amount in the smallest currency unit.
  • Name
    reference
    Type
    string
    Description

    Your reconciliation reference, when provided.

  • Name
    schedule_id
    Type
    string
    Description

    Schedule associated with the payout, when available.

  • Name
    scheduled_at
    Type
    timestamp
    Description

    When the payout was scheduled, when available.

  • Name
    scheduled_by
    Type
    string
    Description

    Actor that scheduled the payout, when available.

  • Name
    sent_at
    Type
    timestamp
    Description

    When the transfer was sent, when available.

  • Name
    source_id
    Type
    string
    Description

    Source identifier, when available.

  • Name
    status
    Type
    string
    Description

    Current state: initialized, scheduled, pending, processing, executing, succeeded, invalid, or canceled.

  • Name
    succeeded_at
    Type
    timestamp
    Description

    When the payout succeeded. Omitted otherwise.


Schedule a payout

Create and schedule a payout to move funds from your available balance to a financial account. The destination must exist and cannot already have an open payout. The requested maximum cannot exceed your configured ceiling.

You'll typically call this endpoint when hitting a payout threshold (weekly settlements, minimum balance triggers), fulfilling vendor payments, or implementing scheduled disbursement runs. The payout executes at or after execute_after—set it to "now" for immediate transfers or schedule future disbursements for specific times.

The response includes the payout ID and initial status. Use the ID with the lookup endpoint to monitor status, public error details, and the final transferred amount.

This operation supports idempotency. A successful response can be replayed with the same idempotency key and request body for 24 hours.

Request attributes

  • Name
    destination_id
    Type
    string
    Description

    Financial account that receives the funds. Scheduling is rejected while another payout for this destination remains open.

  • Name
    execute_after
    Type
    timestamp
    Description

    Optional. Earliest time we'll start processing this payout—ISO 8601 format in UTC. Defaults to "now" if omitted, meaning the payout executes immediately. Set this to schedule future disbursements: "2025-04-15T09:00:00Z" for a specific time, or calculate relative times in your application for recurring schedules.

  • Name
    max_amount
    Type
    integer
    Description

    Maximum amount you authorize, in the smallest currency unit. It must be at least 1 and cannot exceed your configured ceiling. If omitted, the configured ceiling is used. The final amount can be lower.

  • Name
    reference
    Type
    string
    Description

    Optional non-empty reference for reconciliation. It does not need to be unique.

Request

POST
/payouts/schedule
curl https://api.zebo.dev/payouts/schedule \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "destination_id": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0",
    "reference": "PAYOUT-APR-15",
    "max_amount": 250000,
    "execute_after": "2025-04-15T09:00:00Z"
  }'
{
  "payout": {
    "id": "po_yQ2wXm5Dc7Pk9Ls1Vn0RgHaB",
    "destination_id": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0",
    "reference": "PAYOUT-APR-15",
    "status": "scheduled",
    "max_amount": { "currency": "ghs", "value": 250000 },
    "execute_after": "2025-04-15T09:00:00Z",
    "scheduled_at": "2025-04-14T18:32:11.000Z",
    "initiated_at": "2025-04-14T18:32:10.000Z"
  }
}

Lookup a payout

Fetch the current state of a payout to monitor execution progress and retrieve the final transferred amount. You'll typically use this after scheduling a payout to poll for completion or during reconciliation.

Optional lifecycle timestamps, error, and balance_transactions are omitted until they have values.

Request attributes

  • Name
    payout_id
    Type
    string
    Description

    Payout identifier returned when you scheduled the payout. This is your primary lookup key—store it in your system for status checks and reconciliation.

Request

POST
/payouts/lookup
curl https://api.zebo.dev/payouts/lookup \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payout_id": "po_yQ2wXm5Dc7Pk9Ls1Vn0RgHaB"
  }'
{
  "payout": {
    "id": "po_yQ2wXm5Dc7Pk9Ls1Vn0RgHaB",
    "status": "executing",
    "destination_id": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0",
    "amount": { "currency": "ghs", "value": 240000 },
    "initiated_at": "2025-04-14T18:32:10.000Z",
    "sent_at": "2025-04-15T09:01:05.000Z",
    "balance_transactions": [
      "bt_Za2bL9kPxV1c4Gs7Ju0DrQhn",
      "bt_Ps8wC1nDf5m9Qh2Vt6YkRgLb"
    ]
  }
}

Cancel a payout

Cancel a scheduled payout before it executes. This is the escape hatch for payouts scheduled in error, amounts that need adjustment, or disbursements that must be blocked due to compliance holds. Once canceled, the payout is permanently stopped—balance transactions that would have been bundled into it remain in your available balance for future payouts.

Cancellation is only possible when the payout is in scheduled status and its execute_after time is still in the future. A payout that has already started executing—or whose execution window has passed—cannot be canceled. If you need to reverse a completed payout, use a refund or manual balance adjustment instead.

The response returns the updated payout object with status: "canceled" and canceled_at set to the cancellation timestamp.

Request attributes

  • Name
    payout_id
    Type
    string
    Description

    ID of the scheduled payout to cancel. The payout must be in scheduled status with a future execute_after time—attempting to cancel an already-executing, completed, or past-due payout returns an error with details about the current state.

Request

POST
/payouts/cancel
curl https://api.zebo.dev/payouts/cancel \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payout_id": "po_yQ2wXm5Dc7Pk9Ls1Vn0RgHaB"
  }'
{
  "payout": {
    "id": "po_yQ2wXm5Dc7Pk9Ls1Vn0RgHaB",
    "destination_id": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0",
    "status": "canceled",
    "initiated_by": "manual",
    "initiated_at": "2025-04-14T18:32:10.000Z",
    "execute_after": "2025-04-15T09:00:00Z",
    "scheduled_at": "2025-04-14T18:32:11.000Z",
    "canceled_at": "2025-04-14T20:15:44.000Z",
    "max_amount": { "currency": "ghs", "value": 250000 },
    "amount": null
  }
}

Get payout settings

Check your current payout configuration to understand when automatic settlements run and where funds land for each currency. This endpoint returns your payout schedule (how often settlements happen, which day of the week, aging specifications) and your destinations map (which financial account receives funds for each supported currency).

Use this when building dashboards that show payout timing, when onboarding new team members who need to understand your settlement flow, or before scheduling manual payouts to confirm destination accounts are configured correctly. No request body needed—just authenticate and call.

The response includes complete schedule details (interval, timing, aging specifications, settlement rules) and a destinations object mapping currency codes to financial account IDs. If you haven't configured a destination for a currency yet, it won't appear in the map—you'll need to set one with /payouts/set_destinations before automatic payouts can run for that currency.

For a deep dive into what each field means and how to use them, see the Understand payout settings guide.

Request

POST
/payouts/settings
curl https://api.zebo.dev/payouts/settings \
  -H "Authorization: Bearer $COMMERCE_API_KEY"
{
  "settings": {
    "fx_enabled": false,
    "schedule": {
      "name": "weekly",
      "type": "automatic",
      "interval": "weekly",
      "schedule_on": "sunday",
      "aging_spec": {
        "t_plus": "168h",
        "label": "168_hours",
        "abide": "strictly"
      },
      "description": "Automatic weekly payout. Default."
    },
    "destinations": {
      "ghs": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0"
    }
  }
}

Set payout destinations

Configure where automatic payouts land for each currency. Map GHS to your mobile money wallet, USD to your bank account, and so on—each currency routes to its own destination.

Call this when setting up payouts for the first time, switching settlement accounts, or adding new currencies. To remove a currency's destination, send an empty string. Currencies you omit keep their existing values.

Rules

  • Each currency key must be supported (currently ghs—see studio.zebo.dev/specs/currencies for the complete list).
  • Each financial account must exist in your Commerce account and belong to you.
  • Each financial account must not be disconnected—only active accounts can receive payouts.
  • Each financial account's currency must match its map key. You can't send GHS payouts to a USD account.
  • Each financial account must have push operations enabled—accounts without push configuration can't receive payouts.

Request attributes

  • Name
    destinations
    Type
    object
    Description

    Map of currency codes (lowercase) to financial account IDs. Pass an empty string as the value to clear a currency's destination.

Request

POST
/payouts/set_destinations
curl https://api.zebo.dev/payouts/set_destinations \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "destinations": {
      "ghs": "fa_H3cNv7pQf9WbLt2mJs6yXrPq4Kz1Vd5G0aEiUo"
    }
  }'
{
  "settings": {
    "fx_enabled": false,
    "schedule": {
      "name": "weekly",
      "type": "automatic",
      "interval": "weekly",
      "schedule_on": "sunday",
      "aging_spec": {
        "t_plus": "168h",
        "label": "168_hours",
        "abide": "strictly"
      },
      "description": "Automatic weekly payout. Default."
    },
    "destinations": {
      "ghs": "fa_H3cNv7pQf9WbLt2mJs6yXrPq4Kz1Vd5G0aEiUo"
    }
  }
}

Disable automatic payouts

Switch your payout schedule from automatic to manual mode. This stops scheduled automatic settlements—Commerce won't create new payouts until you manually call /payouts/schedule or re-enable automatic payouts.

Use this when you need temporary control over payout timing: during financial audits, when coordinating with accounting periods, or when testing new settlement flows. Your existing scheduled payouts continue executing normally—this only prevents new automatic payouts from being created.

The response includes your updated settings with the schedule switched to manual mode. Your destination mappings remain unchanged—when you re-enable automatic payouts, funds will continue routing to the same financial accounts.

Request

POST
/payouts/disable
curl https://api.zebo.dev/payouts/disable \
  -H "Authorization: Bearer $COMMERCE_API_KEY"
{
  "settings": {
    "schedule": {
      "name": "manual",
      "type": "manual",
      "description": "Manual payout",
      "interval": "never",
      "schedule_on": "never"
    },
    "destinations": {
      "ghs": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0"
    }
  }
}

Enable automatic payouts

Switch your payout schedule from manual to automatic mode. This resumes scheduled automatic settlements on the default weekly cadence—Commerce will create payouts automatically every Sunday for funds that have aged at least 7 days.

Use this when you're ready to resume predictable settlement flows after a period of manual control. Your payout destinations remain unchanged—GHS payouts route to your configured GHS account, USD to your USD account, and so on.

The response includes your updated settings with the schedule switched back to the default weekly automatic mode. Any manual payouts you've already scheduled complete normally—enabling automatic mode doesn't affect existing in-flight transfers.

Request

POST
/payouts/enable
curl https://api.zebo.dev/payouts/enable \
  -H "Authorization: Bearer $COMMERCE_API_KEY"
{
  "settings": {
    "fx_enabled": false,
    "schedule": {
      "name": "weekly",
      "type": "automatic",
      "interval": "weekly",
      "schedule_on": "sunday",
      "aging_spec": {
        "t_plus": "168h",
        "label": "168_hours",
        "abide": "strictly"
      },
      "description": "Automatic weekly payout. Default."
    },
    "destinations": {
      "ghs": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0"
    }
  }
}

Enable FX conversion

Enable automatic foreign-exchange conversion for payouts. When FX is enabled, Commerce converts payout amounts from your balance currency into the destination financial account's local currency at the prevailing exchange rate before transfer.

This endpoint takes no request body—it toggles fx_enabled to true on your payout settings and saves immediately. The updated settings object is returned so you can confirm the change and inspect your current schedule and destination configuration.

Use this when you collect revenue in one currency (e.g. USD) but your financial account operates in a local currency (e.g. UGX or GHS). Commerce handles the conversion and records the applied rate in each payout's balance transactions for reconciliation.

Request

POST
/payouts/enable_fx
curl https://api.zebo.dev/payouts/enable_fx \
  -H "Authorization: Bearer $COMMERCE_API_KEY"
{
  "settings": {
    "fx_enabled": true,
    "schedule": {
      "name": "weekly",
      "type": "automatic",
      "description": "Weekly automatic payout",
      "interval": "weekly",
      "schedule_on": "sunday"
    },
    "destinations": {
      "ghs": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0"
    }
  }
}

Disable FX conversion

Disable automatic foreign-exchange conversion for payouts. When FX is disabled, Commerce disburses payout amounts in your balance currency without conversion—the destination account must accept that currency directly.

This endpoint takes no request body—it toggles fx_enabled to false on your payout settings and saves immediately. The updated settings object is returned so you can confirm the change.

Disable FX when your balance currency matches your destination currency, when you want to handle conversion externally through your financial institution, or when you need precise control over exchange rates and timing for compliance or financial reporting purposes.

Request

POST
/payouts/disable_fx
curl https://api.zebo.dev/payouts/disable_fx \
  -H "Authorization: Bearer $COMMERCE_API_KEY"
{
  "settings": {
    "fx_enabled": false,
    "schedule": {
      "name": "weekly",
      "type": "automatic",
      "description": "Weekly automatic payout",
      "interval": "weekly",
      "schedule_on": "sunday"
    },
    "destinations": {
      "ghs": "fa_Q90wZdd2P7W8hJ1cN9Mx4Rk5sVWBvY3L6pTz8q0"
    }
  }
}

Page through payouts

Retrieve a paginated list of the most recent payouts for the authenticated application. Payouts are sorted by initiated_at in descending order, so page 1 always contains the freshest activity and subsequent pages step back in time.

Request attributes

  • Name
    page_number
    Type
    integer
    Description

    1-based page index to fetch. Must be between 1 and 10 inclusive.

  • Name
    page_size
    Type
    integer
    Description

    Number of payouts per page (1–256). Defaults to 256 when omitted.

Response shape

  • Top level page object includes number, size, and a payouts array.
  • Every entry uses the same payout shape documented above.
  • Optional fields such as amount, error, lifecycle timestamps, and balance_transactions are omitted until available.

Request

POST
/payouts/page
curl https://api.zebo.dev/payouts/page \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "page_number": 1,
    "page_size": 25
  }'
{
  "page": {
    "number": 1,
    "size": 2,
    "payouts": [
      {
        "id": "po_abc123def456",
        "destination_id": "fa_dest001",
        "amount": {
          "value": 50000,
          "currency": "ghs"
        },
        "status": "succeeded",
        "initiated_by": "automatic",
        "initiated_at": "2025-12-15T10:30:00Z",
        "sent_at": "2025-12-15T10:35:00Z",
        "succeeded_at": "2025-12-15T10:35:30Z",
        "balance_transactions": [
          "btx_001",
          "btx_002",
          "btx_003"
        ]
      },
      {
        "id": "po_def456ghi789",
        "destination_id": "fa_dest002",
        "amount": {
          "value": 75000,
          "currency": "ghs"
        },
        "status": "invalid",
        "initiated_by": "manual",
        "error": {
          "type": "destination_error",
          "message": "Insufficient funds in destination account",
          "cause": "Account balance too low",
          "occurred_at": "2025-12-14T15:20:00Z"
        },
        "initiated_at": "2025-12-14T15:00:00Z",
        "failed_at": "2025-12-14T15:20:00Z",
        "expected_at": "2025-12-14T15:00:00Z",
        "balance_transactions": [
          "btx_004",
          "btx_005"
        ]
      }
    ]
  }
}

Was this page helpful?