API and Authentication
Manatee is a server-side Bitcoin payment API. Keep API keys on your backend and never expose them in browser code, mobile apps, or public repositories.
API keys
Each API key is scoped to a Bitcoin network:
| Key type | Network | Use for |
|---|---|---|
| Testnet key | testnet | Integration tests, webhook tests, checkout QA |
| Mainnet key | mainnet | Real Bitcoin payments |
Use testnet keys until the full payment and webhook flow works. Switch to a mainnet key only when your production wallet, webhook endpoint, and order handling are ready.
Authentication
Send the API key as a bearer token:
Authorization: Bearer $MANATEE_API_KEY
Most API calls also require JSON:
Content-Type: application/json
For payment creation, send an Idempotency-Key so retries do not create duplicate payment instructions for the same order:
Idempotency-Key: order-10042-create-payment
Read more in Idempotency Keys.
Create a payment
Use the Bitcoin payment endpoint. Send exactly one amount mode: either amount_sats, or fiat_amount with fiat_currency.
curl -sS -X POST "$MANATEE_API_URL/v1/btc/payments" \
-H "Authorization: Bearer $MANATEE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-10042-create-payment" \
-d '{
"amount_sats": 10000,
"webhook_url": "https://yourapp.example/webhooks/btc",
"required_confirmations": 1,
"expires_in": 3600,
"reference": "order-10042"
}'
For fiat-priced orders, let Manatee create the fixed satoshi quote for the payment. Pricing is handled server-side by the configured provider; API clients and shop plugins do not send provider credentials.
curl -sS -X POST "$MANATEE_API_URL/v1/btc/payments" \
-H "Authorization: Bearer $MANATEE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-10042-create-payment" \
-d '{
"fiat_amount": "51.00",
"fiat_currency": "EUR",
"webhook_url": "https://yourapp.example/webhooks/btc",
"required_confirmations": 1,
"expires_in": 3600,
"reference": "order-10042"
}'
Example response:
{
"id": "pay_abc123",
"address": "tb1q...",
"amount_sats": 85000,
"fiat_amount": "51.00",
"fiat_currency": "EUR",
"exchange_rate": "60000",
"exchange_rate_timestamp": "2026-05-07T10:00:00Z",
"pricing_source": "coinbase",
"status": "pending",
"confirmations": 0,
"required_confirmations": 1,
"network": "testnet",
"webhook_url": "https://yourapp.example/webhooks/btc",
"reference": "order-10042",
"created_at": "2026-05-07T10:00:00Z",
"expires_at": "2026-05-07T11:00:00Z"
}
Show the returned address, amount_sats, and expiry time in your checkout. Store the returned payment id next to your own order ID. If you created the payment from fiat, store the returned quote metadata for reconciliation.
The returned amount_sats is fixed for this payment. Use expires_in to limit how long the checkout quote is valid. Manatee may cache exchange rates briefly on the server side, but the customer-facing quote is bounded by the payment's expires_at.
Retrieve a payment
Fetch the payment by ID:
curl -sS "$MANATEE_API_URL/v1/btc/payments/pay_abc123" \
-H "Authorization: Bearer $MANATEE_API_KEY"
Use retrieval for reconciliation, support views, or fallback polling. For normal order updates, use signed webhooks.
Invalid API key
If a request returns unauthorized:
- Confirm that the
Authorizationheader usesBearer. - Use the key for the same network as the payment you want to create.
- Make sure the key was not rotated or revoked.
- Keep dashboard login separate from API keys; dashboard credentials are not API credentials.
For all endpoints and response schemas, see the generated API Reference.