Axiym
Implementation guides

Create and confirm a payout

View Markdown

Creating a payout validates the instruction, calculates the commercial terms, and returns the payment in PENDING_CONFIRMATION. Review the returned details, then confirm the payout to reserve funds and start compliance review, approval, settlement, and execution.

Before you submit

Prepare the payment data and retrieve the requirements for the selected corridor. Payout creation validates the submitted data.

The funding account must be active, enabled for payouts, and able to cover sourceAmount when you confirm the payout.

Complete example

This example uses POST /payouts with Axiym field names and codes. For mapped input, see the mapped payout API reference.

Supply exactly one of sourceAmount (fixed debit) or destinationAmount (fixed delivery); Axiym calculates the other. This example fixes the amount the recipient receives.

Replace the document placeholders with the base64 encoding of complete sandbox fixtures. See Supporting documents for encoding instructions; the placeholders are not valid document content.

{
  "sourceAccountId": "5c0a9d3e-1f2b-4a6c-8e7d-9b3f5a1c2d4e",
  "destinationAmount": {
    "amount": "56500.00",
    "currency": "PHP"
  },
  "externalReference": "PAYOUT-2026-001",
  "sourceOfFunds": "BUSINESS_INCOME",
  "purpose": "GOODS_PURCHASE",
  "reference": "INV-2026-0917",
  "supportingDocuments": [
    {
      "documentType": "INVOICE",
      "name": "INV-2026-0917.pdf",
      "data": "REPLACE_WITH_BASE64_ENCODED_INVOICE"
    }
  ],
  "sender": {
    "name": "Acme Pte. Ltd.",
    "countryOfIncorporation": "SG",
    "address": {
      "streetName": "1 Raffles Place",
      "city": "Singapore",
      "postalCode": "048616",
      "country": "SG"
    },
    "contact": {
      "email": "payments@acme.example",
      "phoneNumber": "+6591234567"
    },
    "identification": {
      "type": "REGISTRATION_NUMBER",
      "number": "202612345N",
      "country": "SG",
      "documents": [
        {
          "documentType": "REGISTRY_EXTRACT",
          "name": "acme-registry-extract.pdf",
          "data": "REPLACE_WITH_BASE64_ENCODED_REGISTRY_EXTRACT"
        }
      ]
    },
    "relationships": [
      {
        "role": "UBO",
        "firstName": "Alex",
        "lastName": "Tan",
        "nationalities": ["SG"],
        "address": {
          "streetName": "10 Anson Road",
          "city": "Singapore",
          "postalCode": "079903",
          "country": "SG"
        },
        "identification": {
          "type": "PASSPORT",
          "number": "E1234567A",
          "country": "SG",
          "expiryDate": "2033-01-09"
        }
      }
    ]
  },
  "recipient": {
    "businessRelationship": "SUPPLIER",
    "name": "Manila Software Services Inc.",
    "countryOfIncorporation": "PH",
    "address": {
      "streetName": "6789 Ayala Avenue",
      "city": "Makati",
      "region": "Metro Manila",
      "postalCode": "1226",
      "country": "PH"
    },
    "contact": {
      "email": "accounts@manilasoftware.example",
      "phoneNumber": "+639171234567"
    },
    "destination": {
      "accountNumber": "123456789012",
      "currency": "PHP",
      "bank": {
        "bankName": "Example Bank Philippines",
        "address": { "country": "PH" },
        "swiftBic": "BNORPHMMXXX"
      }
    }
  }
}

Omit sender when you pay for yourself: the account holder is then the sender and its onboarded profile is used.

Create the payout

Generate separate keys once for each new payout and retain them for retries:

CREATE_IDEMPOTENCY_KEY="$(uuidgen)"
CONFIRM_IDEMPOTENCY_KEY="$(uuidgen)"

Save the adapted example as payout.json, using your funding account and a unique externalReference for this payout. For a retry, keep the same file, reference, endpoint, and idempotency key. For another payout, use fresh keys and a new reference.

curl --request POST \
  "https://partner-api.sandbox.axiym.io/api/v1/payouts" \
  --header "Authorization: Bearer $AXIYM_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --header "X-Request-Id: $(uuidgen)" \
  --header "Idempotency-Key: $CREATE_IDEMPOTENCY_KEY" \
  --data @payout.json

The API returns 201 Created with status PENDING_CONFIRMATION. Store paymentId and externalReference together. For a mapped payout, also retain the paymentDataMapId sent in the request and the map's contentHash. The payout response does not return the map identifier. Creation returns the commercial terms but does not reserve funds or start processing.

Review before confirmation

Verify in the response:

  • sourceAccount and externalReference are correct;
  • sourceAmount, fee, rate, destinationAmount, and termsExpireAt are acceptable: sourceAmount is the total that will be debited, fee is included in it, and destinationAmount = (sourceAmount − fee) × rate;
  • sender and recipient contain the expected values;
  • the controlled values match the intended Axiym codes, including any saved translations used by a mapped request;
  • the destination bank and account details are correct;
  • reference is what the recipient should see; and
  • every submitted document is listed with its fileId, contentType, and size.

The API does not echo base64 document content. Each document is returned as metadata (documentType, fileId, name, contentType, size) so you can verify that the submitted evidence was accepted.

If the prepared details need a material correction, do not confirm the payout. Create a new payout with the corrected data; confirmation does not accept replacement payment details.

Confirm the payout

Set PAYMENT_ID to the returned paymentId. Both direct and mapped payouts use the same confirmation endpoint. Send no request body and use the separate confirmation key generated above:

curl --request POST \
  "https://partner-api.sandbox.axiym.io/api/v1/payouts/$PAYMENT_ID/confirm" \
  --header "Authorization: Bearer $AXIYM_ACCESS_TOKEN" \
  --header "Idempotency-Key: $CONFIRM_IDEMPOTENCY_KEY"

A successful confirmation returns 200 OK with status PENDING and reserves sourceAmount. The reservation becomes a debit at settlement or is released if the payment ends before settlement.

Confirmation is not compliance approval or proof of delivery. Track the payout through its subsequent status changes.

Handle creation failures

  • the selected corridor is unavailable or the amount is outside its limits;
  • both or neither of sourceAmount and destinationAmount are supplied;
  • direct party data is sent to POST /payouts but does not match the Axiym schema;
  • required baseline party data is missing;
  • a corridor-specific bank or identification field is missing or invalid;
  • a document required by the corridor is missing, or data is not valid base64;
  • mapped data is sent to POST /payouts/mapped with an unknown or incompatible paymentDataMapId;
  • the map is archived, or a non-canonical controlled value has no saved translation;
  • a mapped sender or recipient is incomplete after mapping.

Resolve mapping errors

An unrecognized label returns 422 with unmapped_value at the original request field. For example:

{
  "code": 422,
  "message": "Invalid Parameters",
  "errors": {
    "payment.instruction.reason": [
      {
        "code": "unmapped_value",
        "message": "No saved translation matches this value.",
        "params": {
          "value": "Goods purchase",
          "targetPath": "purpose",
          "paymentDataMapId": "d2a1c7e4-9b3f-4e6a-8c5d-1f0b2a3c4d5e"
        }
      }
    ]
  }
}

If the map contains only goods purchase, the differently capitalized label above does not match. Correct it to an existing saved label or the appropriate Axiym code. If this is a new label your integration needs, review its translation and store a new map before using the new identifier.

For mapped fields, the error identifies the source path inside payment; params.targetPath identifies the corresponding Axiym field. Nested array errors identify the affected entry by index.

An archived map returns 422 with payment_data_map_archived at paymentDataMapId. Select an active map with the appropriate rules, or store a new map. Archiving does not change payouts already created with that map.

After correcting the body or changing paymentDataMapId, start a new request with a new Idempotency-Key. After a timeout or ambiguous response, retry the identical endpoint, body, and key instead.

Handle confirmation failures and retries

Confirmation requires PENDING_CONFIRMATION and an active, payout-enabled funding account with sufficient available balance. Insufficient funds return 422, leave the payout awaiting confirmation, and create no reservation. Resolve the funding shortfall before starting a new confirmation attempt.

If the payout is not confirmed before termsExpireAt, it moves to CANCELED with reasonCode: TERMS_EXPIRED and can no longer be confirmed. Create a new payout to obtain new commercial terms.

After a timeout or ambiguous response, retry the same confirmation path with the same confirmation idempotency key. A successful replay returns the original result without another reservation. Do not repeat payout creation to recover an ambiguous confirmation.

See Confirm a payout for the response contract and Idempotency for retry rules.