PayAgency Logo
Payout

Payout API

This document provides a comprehensive guide to integrating with the Card Payout API. This API enables businesses to transfer funds directly to recipients' credit and debit cards. It covers endpoint details, request/response formats, authentication, and best practices for secure and efficient card disbursements.

API Endpoint

POST https://backend.pay.agency/api/v1/live/payout

Parameters

ParameterTypeDescriptionRequired
wallet_idStringWallet ID of the userYes
first_nameStringFirst name of the cardholderYes
last_nameStringLast name of the cardholderYes
emailStringEmail address of the userYes
addressStringBilling addressYes
countryStringCountry code (ISO 3166-1 alpha-3 format)Yes
cityStringCity of the cardholderYes
stateStringState of the cardholderYes
zipStringZIP or postal codeYes
ip_addressStringIP address of the userYes
phone_numberStringPhone number of the cardholderYes
amountNumberTransaction amount in smallest currency unitYes
currencyStringCurrency code (ISO 4217 format)Yes
card_numberStringCredit/Debit card numberYes
card_expiry_monthStringExpiry month of the card (MM format)Yes
card_expiry_yearStringExpiry year of the card (YYYY format)Yes
webhook_urlStringURL for server-to-server webhook notificationsNO
order_idStringUnique order from merchant sideNO
terminal_idStringConnector unique terminal_id (It's usefull when you want to process transaction on specific connector)NO

Payload

The payload should be sent in JSON format. Below is the structure of the payload:

{
  "wallet_id": "WAL7825818519632620",
  "first_name": "James",
  "last_name": "Dean",
  "email": "james@gmail.com",
  "address": "64 Hertingfordbury Rd",
  "country": "US",
  "city": "Newport",
  "state": "US",
  "zip": "TF10 8DF",
  "ip_address": "127.0.0.1",
  "phone_number": "7654233212",
  "amount": 100,
  "currency": "USD",
  "card_number": "4111111111111111",
  "card_expiry_month": "12",
  "card_expiry_year": "2027",
  "webhook_url": "https://pay.agency/webhook",
  "order_id": "12524AGSDF34DS"
}

Test Cards

For testing your integration, you can use the following test cards:

Success Test Cards

These cards will always result in successful payout transactions:

  • 4222222222222222
  • 5111222233334444

Failed Test Cards

These cards will always result in failed payout transactions:

  • 4333333333333333
  • 5222333344445555

Transaction Limits

Please note that any transaction with an amount greater than 1000 will be automatically declined due to insufficient funds. This limit is in place for testing purposes to help you validate your error handling logic.

Example Responses

Success Response

{
  "status": "SUCCESS",
  "message": "Transaction processed successfully!.",
  "data": {
    "amount": 100,
    "currency": "USD",
    "order_id": null,
    "transaction_id": "FS0186280974141637",
    "customer": {
      "first_name": "James",
      "last_name": "Dean",
      "email": "james@gmail.com"
    },
  }
}

Error Response

{
  "status": "BLOCKED",
  "message": "Currency must match the wallet's currency",
  "data": {
    "amount": 200,
    "currency": "USD",
    "order_id": null,
    "transaction_id": "PA5696597313622467",
    "customer": {
      "first_name": "John",
      "last_name": "Bryan",
      "email": "johnbryan@gmail.com"
    }
  }
}

Redirect URL Handling

In certain scenarios, the API response may include a redirect_url field. This occurs in specific cases where additional information or verification is required to complete the payout transaction. When present, your application should redirect the user to this URL to provide the necessary additional data.

{
"status": "PENDING",
"message": "Additional verification required",
"redirect_url": "https://backend.pay.agency/api/v1/test/payout/verification/FS0186280974141637",
"data": {
  // transaction details
}
}

This is a rare occurrence and typically happens when the payment processor requires extra verification steps for certain transactions or in specific regions.

Integration Examples

The API uses AES-256-CBC encryption to ensure secure transmission of sensitive data. Before sending the payload, you need to encrypt it using your encryption key and a dynamically generated initialization vector (IV). The encrypted payload and the IV must be sent to the API for proper decryption on the server side. This ensures that sensitive details, such as card information, remain secure during transit.

Each integration example demonstrates:

  • How to encrypt the payload using AES-256-CBC.
  • How to generate a random IV.
  • How to include both the encrypted data and the IV in the API request.
const { randomBytes, createCipheriv } = require("crypto");
const axios = require("axios");
 
  // AES Encryption function
  function encryptData(data, key) {
    const iv = randomBytes(16);
    const cipher = createCipheriv(
        "aes-256-cbc",
        Buffer.from(key, "utf-8"),
        iv
    );
    let encrypted = cipher.update(data, "utf-8");
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return iv.toString("hex") + ":" + encrypted.toString("hex");
  }
  const payload = {
    wallet_id: "WAL7825818519632620",
    first_name: "James",
    last_name: "dean",
    email: "dean@gmail.com",
    address: "64 Hertingfordbury Rd",
    country: "US",
    city: "Newport",
    state: "Newport",
    zip: "TF10 8DF",
    ip_address: "127.0.0.1",
    phone_number: "7654233212",
    amount: 100,
    currency: "USD",
    card_number: "4111111111111111",
    card_expiry_month: "12",
    card_expiry_year: "2027",
    webhook_url: "https://webhook.site/40be94f4-293e-4d84-a747-8c934557c0e3",
  };
 
// Encryption key (replace with your actual key)
const encryptionKey = process.env.ENCRYPTION_KEY || "2542b322a40ada01489c5491fe379512";
 
// Encrypt the payload
const encryptedPayload = encryptData(JSON.stringify(payload), encryptionKey);
 
// API request
const url = "https://backend.pay.agency/api/v1/live/payout";
axios
    .post(
        url,
        { payload: encryptedPayload },
        {
          headers: {
              "Content-Type": "application/json",
              "Authorization":"Bearer PA_TEST_62d221bba3bbeb4281ec48c70e3446bce31562c860eeb9dbc02f42ee"
          },
        }
    )
    .then((response) => {
        console.log("API Response:", response.data);
    })
    .catch((error) => {
        console.error("Error:", error.response);
    });

Encryption Key in Settings

The encryption key, used for securing sensitive data, can be found on the Settings page. This key is essential for encryption and decryption processes, ensuring data confidentiality. Make sure to store it securely and avoid sharing it with unauthorized users.

On this page