Caravel Pay Docs

Get started

Get your API keys

One call gives you a merchant id and a secret. Send your site and your payout wallet, and you can create checkouts straight away. Using WooCommerce? The plugin makes this call for you when you save your wallet.

Make the call#

POST/v1/connect

This is the only call you don't sign: it's the one that gives you the keys. Make it from your server.

ParameterDescription
site_urlstringrequiredYour site's HTTPS address, such as https://shop.example. It sets where your return, cancel and callback URLs may point. See below.
payout_addressstringrequiredThe Polygon wallet that receives your payouts, starting with 0x. See your payout wallet.
platformstringrequired"api". (The WooCommerce plugin sends "woocommerce".)
emailstringoptionalWhere we send service notices about this merchant, if ever needed.
POST /v1/connect
curl https://api.caravelpay.app/v1/connect \
  -H "Content-Type: application/json" \
  --data-binary '{
    "site_url": "https://shop.example",
    "payout_address": "0x52908400098527886E0F7030069857D2E4169EE7",
    "email": "[email protected]",
    "platform": "api"
  }'
201 Created
{
  "merchant_id": "mch_7Q2KZX4PRB",
  "secret": "9b2e7c4a1f6d8e3b5a0c9d2f7e4b1a6c3d8f5e2b9a7c4d1e6f3b8a5c2d9e7f4a",
  "status": "active",
  "fee_rate": "2%"
}

The secret is shown once. Keep it on your server, in an environment variable or a secrets store, and never in browser or app code. Lost it? Get new keys.

That's it. Put the two values in CARAVEL_MERCHANT and CARAVEL_SECRET and create your first checkout. You pay 2% Caravel fee and nothing else.

What site_url does#

site_url decides where your checkouts may send buyers and webhooks. Your return_url, cancel_url and callback_url must be HTTPS on that site, with or without www:

site_urlAllowed URLs start with
https://shop.examplehttps://shop.example/ or https://www.shop.example/

Buyers never see it. The hosted checkout shows Caravel Pay, the amount and the ways to pay, and no store name, logo or address.

Your payout wallet#

  • Use an ordinary Polygon wallet that you control, such as MetaMask, Rabby or a hardware wallet. Contracts, token addresses and exchange deposit contracts are refused.
  • Payouts arrive in the token the buyer paid with, never swapped. Card payments arrive as USDC.
  • One wallet can receive payouts for several sites.

Payouts and fees has the details.

Change your wallet or secret#

Call POST /v1/connect again with the new details. Each call creates a new merchant with its own id and secret; existing keys are never sent out again. Then:

  1. Switch new checkouts to the new keys. Their payouts go to the wallet you just sent.

  2. Keep the old keys for a day. Checkouts you already created finish on the old merchant: they pay out to the old wallet, and their webhooks are signed with the old secret. Webhooks are retried for up to 24 hours, so keep the old secret at least 24 hours after your last checkout on it.

Every webhook carries Caravel-Merchant, so verify each one with the secret that belongs to that merchant:

Two sets of keys during a switch
const secrets = {
  [process.env.CARAVEL_MERCHANT]: process.env.CARAVEL_SECRET,         // new keys
  [process.env.CARAVEL_OLD_MERCHANT]: process.env.CARAVEL_OLD_SECRET, // until the old checkouts finish
};
const secret = secrets[req.get("Caravel-Merchant")];
if (!secret) return res.sendStatus(401);

If an old secret may have leaked, get new keys the same way and email [email protected] with the old merchant id so we can pause it.

The WooCommerce plugin does all of this for you when you save a new wallet or click Reconnect.

Status#

status is active: you can create checkouts right away. If it is pending_review, checkouts open once the merchant is approved. Merchant status lists every value.

Errors#

CodeStatusWhat to do
invalid_request400A field is missing or unknown, or the payout wallet can't receive payouts. param names the field.
invalid_url400Send site_url as a plain HTTPS address, like https://shop.example.
limit_exceeded409This wallet already receives payouts for the maximum number of merchants. Use another wallet.
rate_limited429Too many calls from your server. Wait Retry-After seconds.
service_unavailable503New merchants are briefly paused. Retry after Retry-After seconds.

All codes are on the Errors page.