JamiDev

Fees & limits

Every number in JamiDev on one page — money units, fees, payout limits, timeouts, rate limits, sandbox numbers and error codes.

The numbers other pages mention, in one place. If something here disagrees with another page, this page and the API are right; tell us at support@jami.bio.

Money

RuleValue
CurrencyETB only
Unit in the APIInteger santim (ETB minor units). 10000 = 100.00 ETB.
Charged to the buyerExactly the product's price, or the custom amount you sent. Nothing is added at checkout.
Custom amount (no product)Integer santim, at least 100 (1.00 ETB)
pwyw product amountInteger santim, at or above the product's minimum

Fees

FeeValue
Monthly or setup feeNone
At checkoutNone. The buyer pays exactly the price or amount.
JamiDev fee on withdrawal7% of the amount withdrawn, unless Jami set a custom rate on your account
Government tax on withdrawalThe rate Jami's platform settings apply (shown as taxAmount)
How fees are takenCut from the amount withdrawn: netAmount = amount − feeAmount − taxAmount
RoundingEach part rounded to the nearest santim

The server is authoritative. Read feeAmount, taxAmount and netAmount on the withdrawal; Jami.computeWithdrawalQuote is an offline estimate using the defaults.

Payouts

LimitValue
Minimum withdrawal100.00 ETB (10000)
Paid out automaticallyUp to 10,000.00 ETB (1000000). Above that, manual review.
Per organization, rolling 24 hours100,000.00 ETB (10000000). Past it: 429.
Per withdrawal maximumThe organization's withdrawable earnings (GET /balance)
RequirementsProduction organization, Developer Mode on, approved KYC
MethodsTelebirr, M-Pesa, CBE Birr

Wallet transfers (OAuth)

For wallet:send on behalf of a signed-in user:

LimitValue
Per transfer1.00 to 10,000.00 ETB
Per user, per app, rolling 24 hours50,000.00 ETB. Past it: 429 daily_cap_exceeded.
Idempotency keyRequired, at least 8 characters
SenderMust have approved KYC

Checkout

RuleValue
Session lifetime30 minutes
productIdThe product's p_… token or its id. Must be published and in your organization. Omit it for a custom amount.
description (custom amount)Required, 1 to 120 characters
metadataUp to 20 keys of 1 to 40 characters; string, number or boolean values, stored as strings of up to 500 characters. API token only.
Payment methodstelebirr, mpesa, cbe
Orders per sessionAt most one
Payment link (no gateway)Lasts the session's 30 minutes. The buyer can retry failed attempts on it; a new attempt is refused for 150 seconds while a prompt is out. API token only.
SDK waitForCheckoutPolls every 2 s, gives up after 5 minutes (poll_timeout)

Products

RuleValue
title1 to 120 characters
descriptionUp to 5,000 characters
Pricing modelfixed, pwyw or free. Locked after creation (422 on change).
Product typesOne-time only
Created fromThe Products API, the SDK, the MCP server or the dashboard

Rate limits

EndpointLimit
POST /checkout with a tokenA bucket per token: bursts of up to 200, refilling at 20 per second
POST /checkout without a token (hosted pages)40 per 5 minutes per IP
Payment link attempts (POST /pay/{payToken})30 per 5 minutes per IP
OAuth endpointsSee Sign in with Jami

A 429 from POST /withdrawals means the daily payout cap, not a request rate.

Webhooks

RuleValue
Signature headerX-JamiDev-Signature: t=<unix seconds>,v1=<hex>
AlgorithmHMAC-SHA256 over "{t}.{raw body}" with the subscription secret
SDK replay window300 seconds (toleranceSec)
Response timeout10 seconds
Retries1 min, 5 min, 30 min, 2 h, 12 h (5 attempts in total)

Sandbox

PhoneResult
251900000001Instant success
251900000002Instant failure (payment_failed)
Anything elseSimulator page with Approve and Fail buttons

Tokens: jamidev_test_… in sandbox, jamidev_live_… in production. A token stops working when its organization switches environment.

Checkout failure codes

Set on expired sessions as failure.code.

CodeMeaning
payment_rejectedThe provider refused it within seconds, before a prompt reached the phone
payment_failedFailed after the prompt (wrong PIN, canceled on the phone, low balance), or no detail given
payment_canceledThe buyer canceled
payment_timed_outThe buyer didn't answer the prompt in time
initiate_failedThe payment couldn't be started; message has the provider's reason
session_expired30 minutes passed without a payment

New codes may be added. Treat unknown ones like payment_failed.

Errors

HTTPBodySDK errorTypical cause
400{ "error": "…" }JamiValidationErrorA field failed validation; the message names it
401{ "message": "…" }JamiAuthErrorMissing, malformed, revoked or wrong-environment token (.hint set for the last)
402{ "error": "…" }JamiErrorWithdrawal: the owner's wallet can't cover it right now
404{ "error": "…" }JamiErrorNot found, or not yours (the API doesn't tell them apart)
429{ "error": "…" }JamiRateLimitErrorCheckout rate limit, or the daily payout cap
502{ "error": "…" }JamiErrorThe payment provider rejected the checkout
——JamiSignatureErrorA webhook failed verification
——JamiWalletErrorA wallet call failed; code holds the server's reason

Every SDK error has status, code and, when the response had one, requestId. Include requestId when you contact support.

On this page