EERTHAPartner API Log in Create account
Ertha Payment Solution

Send payouts to Haiti,
programmatically.

The ERTHA Partner API lets your platform deliver money to any recipient in Haiti in Gourdes (HTG) with a single signed request. Prepaid balance, sandbox testing, idempotent retries, and webhooks — built for businesses that move money at scale.

Base URL https://api.erthapay.com
Quickstart

From zero to first payout

Every account starts in Sandbox, where a fake balance lets you build and test with zero real money moving.

1

Create an account

Sign up for a partner account and receive your Sandbox key pair instantly.

2

Sign a request

Sign each call with HMAC-SHA256 using your secret. No secret ever leaves your server.

3

Go live

Fund your balance and switch to your Live keys. Your account manager enables Live payouts.

Authentication

Signing requests

Requests are authenticated with an HMAC-SHA256 signature — there are no bearer tokens and your secret is never transmitted. Each request carries three headers:

HeaderValue
x-partner-keyYour public key (pk_test_… / pk_live_…)
x-partner-timestampCurrent time in milliseconds. Must be within ±5 minutes.
x-partner-signatureHex HMAC-SHA256 of the signing string, keyed by your secret.

The signing string

Concatenate the timestamp, the HTTP method and path, and the raw request body — exactly as shown. For requests with no body (e.g. GET), the body is empty, so the string ends in a trailing dot.

Keep secrets in the environment. Read your key and secret from environment variables — never hard-code a secret in your source or ship it to a browser.

cURL Node.js Python
# signing string = "{ts}.{METHOD} {path}.{body}"
TS=$(($(date +%s)*1000))
BODY='{"recipient":"+509XXXXXXXX","amount":1000,"reference":"order-1001"}'
MSG="$TS.POST /transfers.$BODY"
SIG=$(printf '%s' "$MSG" | openssl dgst -sha256 \
      -hmac "$ERTHA_API_SECRET" | sed 's/^.* //')

curl https://api.erthapay.com/transfers \
  -H "content-type: application/json" \
  -H "x-partner-key: $ERTHA_API_KEY" \
  -H "x-partner-timestamp: $TS" \
  -H "x-partner-signature: $SIG" \
  -d "$BODY"
Environments

Sandbox & Live

Two isolated key pairs. Which key signs the request decides the mode — the same endpoints serve both.

Sandboxpk_test_… / sk_test_…

A fake balance and simulated payouts. Nothing real moves — perfect for building and CI. Recipients ending in 0000 simulate an invalid number.

Livepk_live_… / sk_live_…

Real payouts drawn from your prepaid balance. Live delivery is enabled per account by your ERTHA account manager once you're ready.

Endpoint

Create a payout

POST/transfers

Sends a payout to a recipient's mobile money number in Haiti. The amount is a whole number of Gourdes. Provide your own reference — it's how you retrieve status later and how retries stay safe.

Body paramType
recipientstringRequired
Recipient mobile number in +509XXXXXXXX format.
amountintegerRequired
Amount in whole HTG (Gourdes). Must be a positive integer.
referencestringRequired
Your unique id for this payout. Reuse it to retry safely.
Response200 OK
{
  "id": "txn_9f3c1a20",
  "reference": "order-1001",
  "status": "pending",
  "amount": 1000,
  "currency": "HTG",
  "livemode": true
}

Statuses. A payout is pending, then resolves to paid or failed. Poll the retrieve endpoint or subscribe to webhooks.

Endpoint

Retrieve a payout

GET/transfers/{reference}

Fetch the current state of a payout by the reference you created it with (or by its txn_ id). Read-only and safe to poll.

Path paramType
referencestringRequired
Response200 OK
{
  "id": "txn_9f3c1a20",
  "reference": "order-1001",
  "status": "paid",
  "amount": 1000,
  "currency": "HTG"
}
Endpoint

Validate a recipient

POST/recipients/validate

Confirm a recipient number resolves to a real account and return the registered name — check before you send, and show your user who they're paying.

Body paramType
recipientstringRequired
Response200 OK
{
  "recipient": "+509XXXXXXXX",
  "name": "Jean Baptiste",
  "livemode": true
}
Endpoint

Get balance

GET/balance

Your available prepaid balance, in Gourdes. In Sandbox this returns your fake test balance.

Response200 OK
{
  "balance": 96379,
  "currency": "HTG",
  "livemode": true
}
Reliability

Idempotency

Networks fail. Retries shouldn't cost money twice.

Every payout carries your reference. If a request times out, re-send the same reference with the same body — you'll get the original payout back, never a duplicate. Re-using a reference with a different amount or recipient is rejected with 409 DUPLICATE_REQUEST, so a mistaken reuse can't silently overwrite a real payment.

Reference

Errors & status codes

Errors return a JSON body of the shape { "error": "CODE" }. Never surface a raw error to your end user — map it to your own copy.

HTTPCodeMeaning
401UNAUTHORIZEDBad signature, wrong key, or a timestamp outside the ±5-minute window.
400INVALID_REQUESTMissing or unknown fields in the body.
400INVALID_AMOUNTAmount is not a positive whole number of HTG.
400REFERENCE_REQUIREDA signed reference is required to create a payout.
409DUPLICATE_REQUESTReference reused with a different payload.
429RATE_LIMITEDToo many requests — back off and retry after the returned delay.
503SERVICE_UNAVAILABLETemporary — safe to retry with the same reference.