API Reference

One REST API to bank your farmers. Everything you create belongs to your organization. Amounts are in Ghana cedis (GHS).

1. Get a key

Create an organization, then open Developers. ffsp_test_ keys use simulated money; ffsp_live_ keys move real money through GCB.

2. Authenticate

BASE=https://<your-domain>/api/public/v1
FFSP_KEY=ffsp_test_xxxxxxxxxxxxxxxx

curl "$BASE/ping" -H "Authorization: Bearer $FFSP_KEY"
# {"ok":true,"mode":"test"}

3. Safe retries

Send an Idempotency-Key header on every POST. Repeating a request with the same key returns the original result instead of moving money twice.

Errors

{ "error": { "code": "insufficient_funds", "message": "Farmer has insufficient balance" } }
  • 401 unauthorized — Missing, invalid or revoked key
  • 404 not_found — Resource doesn't exist in your org
  • 409 insufficient_funds — Farmer balance too low
  • 409 insufficient_wallet_funds — Fund your organization wallet
  • 409 account_frozen — Farmer account is frozen
  • 422 validation_error — See error.details
  • 502 bank_error — GCB rejected or is unavailable
  • 500 internal_error — Retry with the same Idempotency-Key

Webhooks

Events: transaction.success, transaction.pending, transaction.failed, farmer.created, loan.disbursed, loan.repayment. Verify every request:

// Node.js
const crypto = require("crypto");
const ts = req.headers["ffsp-timestamp"];
const expected = "sha256=" + crypto.createHmac("sha256", WEBHOOK_SECRET)
  .update(`${ts}.${rawBody}`).digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["ffsp-signature"])))
  return res.status(401).end();

Farmers

POST/farmers

Create a farmer account

Opens a GCB savings account under your organization.

  • full_name* — 2–120 chars
  • phone* — Ghana number, 0XXXXXXXXX or +233
  • ghana_card — GHA-000000000-0
  • external_id — Your own ID, unique per org
  • email, community, region, metadata — Optional
curl -X POST "$BASE/farmers" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"full_name":"Ama Owusu","phone":"0241234567","ghana_card":"GHA-000000000-0","community":"Kumawu","region":"Ashanti","external_id":"coop-0042"}'
Response
{
  "id": "6f1c2c8e-…",
  "object": "farmer",
  "external_id": "coop-0042",
  "full_name": "Ama Owusu",
  "phone": "0241234567",
  "account_number": "DOS0241234567",
  "balance": 0,
  "currency": "GHS",
  "status": "active",
  "kyc_status": "unverified",
  "mode": "test"
}
GET/farmers?limit=20&offset=0

List farmers

Paginated. Filter with ?external_id=.

curl -X GET "$BASE/farmers?limit=20&offset=0" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "6f1c2c8e-…",
      "object": "farmer",
      "external_id": "coop-0042",
      "full_name": "Ama Owusu",
      "phone": "0241234567",
      "account_number": "DOS0241234567",
      "balance": 0,
      "currency": "GHS",
      "status": "active",
      "kyc_status": "unverified",
      "mode": "test"
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
GET/farmers/{id}

Get a farmer

curl -X GET "$BASE/farmers/{id}" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "id": "6f1c2c8e-…",
  "object": "farmer",
  "external_id": "coop-0042",
  "full_name": "Ama Owusu",
  "phone": "0241234567",
  "account_number": "DOS0241234567",
  "balance": 0,
  "currency": "GHS",
  "status": "active",
  "kyc_status": "unverified",
  "mode": "test"
}
PATCH/farmers/{id}

Update or freeze

Set status to frozen to block all money movement.

curl -X PATCH "$BASE/farmers/{id}" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"status":"frozen"}'
Response
{
  "id": "6f1c2c8e-…",
  "object": "farmer",
  "external_id": "coop-0042",
  "full_name": "Ama Owusu",
  "phone": "0241234567",
  "account_number": "DOS0241234567",
  "balance": 0,
  "currency": "GHS",
  "status": "frozen",
  "kyc_status": "unverified",
  "mode": "test"
}
GET/farmers/{id}/balance

Get balance

curl -X GET "$BASE/farmers/{id}/balance" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "balance",
  "farmer_id": "6f1c…",
  "account_number": "DOS0241234567",
  "balance": 150,
  "currency": "GHS"
}
GET/farmers/{id}/transactions

Statement

Paginated transaction history.

curl -X GET "$BASE/farmers/{id}/transactions" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "a83b…",
      "object": "transaction",
      "type": "credit",
      "direction": "C",
      "amount": 150,
      "currency": "GHS",
      "status": "success",
      "reference": "FFSP-M2K…",
      "farmer_id": "6f1c…"
    }
  ],
  "total": 1
}

Money movement

POST/farmers/{id}/credit

Credit

Moves money from your organization wallet into the farmer's account.

curl -X POST "$BASE/farmers/{id}/credit" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"amount":150,"narration":"Cocoa bonus"}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "credit",
  "direction": "C",
  "amount": 150,
  "currency": "GHS",
  "status": "success",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
POST/farmers/{id}/debit

Debit

Moves money from the farmer's account back to your organization wallet.

curl -X POST "$BASE/farmers/{id}/debit" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"amount":40,"narration":"Input purchase"}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "debit",
  "direction": "D",
  "amount": 40,
  "currency": "GHS",
  "status": "success",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
POST/transfers

Transfer

Farmer to farmer, within your organization.

curl -X POST "$BASE/transfers" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"from_farmer_id":"6f1c…","to_farmer_id":"9e0a…","amount":25,"narration":"Shared transport"}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "transfer_out",
  "direction": "D",
  "amount": 25,
  "currency": "GHS",
  "status": "success",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
POST/farmers/{id}/deposits/momo

Deposit from mobile money

Farmer approves a prompt on their phone. Returns pending; you get a webhook when it settles.

  • network* — MTN | TELECEL | AT
curl -X POST "$BASE/farmers/{id}/deposits/momo" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"momo_number":"0241234567","network":"MTN","amount":100}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "momo_deposit",
  "direction": "C",
  "amount": 150,
  "currency": "GHS",
  "status": "pending",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
POST/farmers/{id}/withdrawals/momo

Withdraw to mobile money

Funds are reserved immediately and refunded automatically if the payout fails.

curl -X POST "$BASE/farmers/{id}/withdrawals/momo" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"momo_number":"0241234567","network":"MTN","amount":50}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "momo_withdrawal",
  "direction": "D",
  "amount": 150,
  "currency": "GHS",
  "status": "pending",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
POST/farmers/{id}/withdrawals/bank

Withdraw to a bank

Instant transfer (GIP) to any Ghana bank. Verify the account first.

curl -X POST "$BASE/farmers/{id}/withdrawals/bank" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"bank_code":"300304","account_number":"1234567890123","account_name":"Ama Owusu","amount":200}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "bank_withdrawal",
  "direction": "D",
  "amount": 150,
  "currency": "GHS",
  "status": "pending",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
GET/transactions/{id}

Get a transaction

Also re-checks status with the bank if still pending.

curl -X GET "$BASE/transactions/{id}" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "credit",
  "direction": "C",
  "amount": 150,
  "currency": "GHS",
  "status": "success",
  "reference": "FFSP-M2K…",
  "farmer_id": "6f1c…"
}
GET/transactions?status=pending

List transactions

curl -X GET "$BASE/transactions?status=pending" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "a83b…",
      "object": "transaction",
      "type": "credit",
      "direction": "C",
      "amount": 150,
      "currency": "GHS",
      "status": "success",
      "reference": "FFSP-M2K…",
      "farmer_id": "6f1c…"
    }
  ]
}

Loans

POST/loans

Issue a loan

Disburses the principal from your wallet into the farmer's account. Interest is flat.

curl -X POST "$BASE/loans" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"farmer_id":"6f1c…","principal":500,"interest_rate":10,"term_months":6,"purpose":"Fertilizer"}'
Response
{
  "id": "c11d…",
  "object": "loan",
  "farmer_id": "6f1c…",
  "principal": 500,
  "interest_rate": 10,
  "term_months": 6,
  "total_due": 550,
  "amount_repaid": 0,
  "outstanding": 550,
  "status": "active",
  "due_date": "2027-04-13"
}
GET/loans/{id}

Get a loan

curl -X GET "$BASE/loans/{id}" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "id": "c11d…",
  "object": "loan",
  "farmer_id": "6f1c…",
  "principal": 500,
  "interest_rate": 10,
  "term_months": 6,
  "total_due": 550,
  "amount_repaid": 0,
  "outstanding": 550,
  "status": "active",
  "due_date": "2027-04-13"
}
POST/loans/{id}/repayments

Record a repayment

Debits the farmer's savings into your wallet. Loan closes when fully repaid.

curl -X POST "$BASE/loans/{id}/repayments" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"amount":100}'
Response
{
  "loan": {
    "id": "c11d…",
    "object": "loan",
    "farmer_id": "6f1c…",
    "principal": 500,
    "interest_rate": 10,
    "term_months": 6,
    "total_due": 550,
    "amount_repaid": 100,
    "outstanding": 450,
    "status": "active",
    "due_date": "2027-04-13"
  },
  "transaction": {
    "id": "a83b…",
    "object": "transaction",
    "type": "loan_repayment",
    "direction": "D",
    "amount": 100,
    "currency": "GHS",
    "status": "success",
    "reference": "FFSP-M2K…",
    "farmer_id": "6f1c…"
  }
}

Organization & banks

GET/organization/wallet

Wallet balance

Your organization's float that funds credits and loans.

curl -X GET "$BASE/organization/wallet" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "wallet",
  "account_number": "DOS0200000001",
  "balance": 9850,
  "currency": "GHS"
}
POST/organization/wallet/fund

Fund wallet from MoMo

curl -X POST "$BASE/organization/wallet/fund" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"momo_number":"0241234567","network":"MTN","amount":1000}'
Response
{
  "id": "a83b…",
  "object": "transaction",
  "type": "wallet_funding",
  "direction": "C",
  "amount": 150,
  "currency": "GHS",
  "status": "pending",
  "reference": "FFSP-M2K…",
  "farmer_id": null
}
GET/banks

List banks

Bank codes for withdrawals.

curl -X GET "$BASE/banks" \
  -H "Authorization: Bearer $FFSP_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "code": "300304",
      "name": "GCB Bank"
    }
  ]
}
POST/accounts/verify

Verify account name

curl -X POST "$BASE/accounts/verify" \
  -H "Authorization: Bearer $FFSP_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"account_number":"1234567890123","bank_code":"300304"}'
Response
{
  "account_number": "1234567890123",
  "bank_code": "300304",
  "account_name": "AMA OWUSU"
}