Payouts

Send money to mobile money wallets and bank accounts.

Payouts API

The Payouts API allows you to send money to mobile money wallets and bank accounts in Ghana.

The Payout Object

{
  "id": "po_abc123def456",
  "object": "payout",
  "amount": 100,
  "currency": "GHS",
  "fee": 1.50,
  "status": "completed",
  "destination": {
    "type": "mobile_money",
    "provider": "mtn",
    "number": "024****567",
    "name": "John Doe"
  },
  "description": "Salary payment",
  "metadata": {
    "employee_id": "123"
  },
  "provider_reference": "OP123456789",
  "failure_reason": null,
  "created_at": "2024-01-15T10:00:00Z",
  "completed_at": "2024-01-15T10:00:05Z"
}

Attributes

AttributeTypeDescription
idstringUnique identifier
objectstringAlways "payout"
amountnumberAmount in GHS
currencystringCurrency code (GHS)
feenumberTransaction fee in GHS
statusstringcreated, pending, processing, succeeded, failed, cancelled
destinationobjectDestination account details
destination.typestringmobile_money, bank_transfer, or shika_wallet
destination.providerstringProvider (e.g., mtn, telecel, airteltigo)
destination.numberstringMasked account/phone number or consumer account ID
destination.namestringRecipient name
descriptionstringPayout description
metadataobjectCustom metadata
provider_referencestringProvider transaction reference
failure_reasonstringError message if failed
created_atstringCreation timestamp
completed_atstringCompletion timestamp

Create a Payout

Sends money to a mobile money wallet or bank account.

POST /v1/payouts

Request Body

ParameterTypeRequiredDescription
amountnumberYesAmount in GHS (e.g., 100 for GHS 100.00)
currencystringNoCurrency (default: GHS)
destinationobjectYesDestination account details
destination.typestringYesmobile_money, bank_transfer, or shika_wallet
destination.phone_numberstringYes*Phone number (for mobile money or shika_wallet lookup)
destination.providerstringNoProvider code (auto-detected from phone)
destination.account_numberstringYes*Account number (for bank transfer)
destination.bank_codestringYes*Bank code (for bank transfer)
destination.account_idstringYes*Consumer account ID (for shika_wallet, e.g., acc_xxx)
destination.account_namestringNoRecipient name
otp_codestringYes6-digit OTP code for verification
descriptionstringNoPayout description
metadataobjectNoCustom metadata

Before initiating a payout, you must first request an OTP using the OTP API. The OTP is sent to the merchant's registered phone number and must be verified within 10 minutes.

Mobile Money Payout

curl -X POST https://api.shikacreators.com/v1/payouts \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100,
    "currency": "GHS",
    "destination": {
      "type": "mobile_money",
      "phone_number": "0241234567",
      "account_name": "John Doe"
    },
    "otp_code": "123456",
    "description": "Salary payment",
    "metadata": {
      "employee_id": "123"
    }
  }'
const payout = await shikacreators.payouts.create({
  amount: 100,
  currency: 'GHS',
  destination: {
    type: 'mobile_money',
    phone_number: '0241234567',
    account_name: 'John Doe'
  },
  otp_code: '123456',
  description: 'Salary payment',
  metadata: {
    employee_id: '123'
  }
})
payout = client.payouts.create(
    amount=100,
    currency='GHS',
    destination={
        'type': 'mobile_money',
        'phone_number': '0241234567',
        'account_name': 'John Doe'
    },
    otp_code='123456',
    description='Salary payment',
    metadata={'employee_id': '123'}
)
$payout = $shikacreators->payouts->create([
    'amount' => 100,
    'currency' => 'GHS',
    'destination' => [
        'type' => 'mobile_money',
        'phone_number' => '0241234567',
        'account_name' => 'John Doe'
    ],
    'otp_code' => '123456',
    'description' => 'Salary payment',
    'metadata' => ['employee_id' => '123']
]);

Bank Transfer Payout

curl -X POST https://api.shikacreators.com/v1/payouts \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500,
    "currency": "GHS",
    "destination": {
      "type": "bank_transfer",
      "account_number": "1234567890",
      "bank_code": "GCB",
      "account_name": "John Doe"
    },
    "otp_code": "123456",
    "description": "Vendor payment"
  }'
const payout = await shikacreators.payouts.create({
  amount: 500,
  currency: 'GHS',
  destination: {
    type: 'bank_transfer',
    account_number: '1234567890',
    bank_code: 'GCB',
    account_name: 'John Doe'
  },
  otp_code: '123456',
  description: 'Vendor payment'
})
payout = client.payouts.create(
    amount=500,
    currency='GHS',
    destination={
        'type': 'bank_transfer',
        'account_number': '1234567890',
        'bank_code': 'GCB',
        'account_name': 'John Doe'
    },
    otp_code='123456',
    description='Vendor payment'
)

Shika Wallet Payout

Send money directly to a consumer's Shika Wallet. This method is instant — no external payment provider is involved.

curl -X POST https://api.shikacreators.com/v1/payouts \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50,
    "currency": "GHS",
    "destination": {
      "type": "shika_wallet",
      "account_id": "acc_abc123def456"
    },
    "otp_code": "123456",
    "description": "Cashback reward"
  }'
const payout = await shikacreators.payouts.create({
  amount: 50,
  currency: 'GHS',
  destination: {
    type: 'shika_wallet',
    account_id: 'acc_abc123def456'
  },
  otp_code: '123456',
  description: 'Cashback reward'
})
payout = client.payouts.create(
    amount=50,
    currency='GHS',
    destination={
        'type': 'shika_wallet',
        'account_id': 'acc_abc123def456'
    },
    otp_code='123456',
    description='Cashback reward'
)

You can also use phone_number instead of account_id to look up the consumer by their registered phone number.

Shika Wallet payouts are completed instantly. The status will be completed in the response — no need to poll for status updates.

Supported Providers

Mobile Money

ProviderCodePhone Prefixes
MTN Mobile Moneymtn024, 025, 053, 054, 055, 059
Telecel Cashtelecel020, 050
AirtelTigo Moneyairteltigo026, 027, 056, 057

The provider is automatically detected from the phone number. You can optionally specify it explicitly.

Banks

BankCode
Ghana Commercial BankGCB
Ecobank GhanaECO
Stanbic BankSBG
Standard CharteredSCB
Absa BankABSA
Fidelity BankFBN
CalBankCAL
Access BankABG
UBA GhanaUBA
Zenith BankZBG

Contact support for the complete list of supported banks.

Response

{
  "id": "po_abc123def456",
  "object": "payout",
  "amount": 100,
  "currency": "GHS",
  "fee": 1.50,
  "status": "completed",
  "destination": {
    "type": "mobile_money",
    "provider": "mtn",
    "number": "024****567",
    "name": "John Doe"
  },
  "description": "Salary payment",
  "metadata": {
    "employee_id": "123"
  },
  "provider_reference": "OP123456789",
  "failure_reason": null,
  "created_at": "2024-01-15T10:00:00Z",
  "completed_at": "2024-01-15T10:00:05Z"
}

Retrieve a Payout

Retrieves a payout by ID.

GET /v1/payouts/:id
curl https://api.shikacreators.com/v1/payouts/po_abc123def456 \
  -H "Authorization: Bearer sk_test_..."
const payout = await shikacreators.payouts.retrieve('po_abc123def456')
payout = client.payouts.retrieve('po_abc123def456')

List Payouts

Returns a list of payouts.

GET /v1/payouts

Query Parameters

ParameterTypeDescription
limitintegerNumber of results (1-100)
starting_afterstringCursor for pagination
statusstringFilter by status
curl "https://api.shikacreators.com/v1/payouts?status=succeeded&limit=10" \
  -H "Authorization: Bearer sk_test_..."
const payouts = await shikacreators.payouts.list({
  status: 'succeeded',
  limit: 10
})
payouts = client.payouts.list(status='succeeded', limit=10)

Response

{
  "object": "list",
  "data": [
    {
      "id": "po_abc123def456",
      "object": "payout",
      "amount": 100,
      "status": "succeeded",
      ...
    }
  ],
  "has_more": true,
  "url": "/v1/payouts"
}

Payout Statuses

StatusDescription
createdPayout has been created
pendingPayout is queued for processing
processingPayout is being processed by the provider
succeededPayout was successful
failedPayout failed
cancelledPayout was cancelled

Error Codes

CodeDescription
insufficient_balanceNot enough balance in your account
invalid_destinationDestination account is invalid
recipient_unavailableRecipient's account is unavailable
daily_limit_exceededDaily payout limit exceeded
amount_too_smallAmount below minimum (GHS 1.00)
amount_too_largeAmount above maximum
otp_verification_requiredOTP verification is required
invalid_phone_numberInvalid Ghana phone number

Webhook Events

EventDescription
payout.createdPayout was created
payout.pendingPayout is pending processing
payout.completedPayout was successful
payout.failedPayout failed
app.post('/webhooks', (req, res) => {
  const event = Webhook.constructEvent(req.body, signature, secret)

  switch (event.type) {
    case 'payout.completed':
      const payout = event.data.object
      console.log(`Payout ${payout.id} completed!`)
      break
    case 'payout.failed':
      const failedPayout = event.data.object
      console.log(`Payout failed: ${failedPayout.failure_reason}`)
      break
  }

  res.json({ received: true })
})

OTP Verification Flow

Payouts require OTP verification for security. Here's the complete flow:

Step 1: Request OTP

curl -X POST https://api.shikacreators.com/v1/otp/request \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "purpose": "PAYOUT"
  }'

Step 2: Verify OTP

curl -X POST https://api.shikacreators.com/v1/otp/verify \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "code": "123456",
    "purpose": "PAYOUT"
  }'

Step 3: Create Payout

Use the verified OTP code when creating the payout:

curl -X POST https://api.shikacreators.com/v1/payouts \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100,
    "destination": {
      "type": "mobile_money",
      "phone_number": "0241234567"
    },
    "otp_code": "123456"
  }'

The OTP is valid for 10 minutes after verification. If expired, you'll need to request a new OTP.