Installation
Connecting a storefront to ShotPay takes four things: an account that is cleared to sell, an API key, somewhere for us to deliver webhooks, and one call to prove the pair works.
1. Open a merchant account
Sign up at the ShotPay dashboard and work through onboarding — business information, then a review of the account, then the FFL upload. Approval opens your sandbox; verifying the licence is what opens live.
| To do this | You need |
|---|---|
| Issue a sandbox key and open sandbox sessions | An approved account, with a verified email address. |
| Issue a live key and take real orders | The above, plus a verified FFL licence. |
Sandbox opens as soon as your account is approved, and the whole integration can be built against it while the FFL is in review. See Sandbox.
2. Issue an API key
In the dashboard, go to API keys. The mode toggle at the top of the dashboard decides which half you are issuing for — a key minted in sandbox can never read a live session, or the other way round.
Give the key a name and issue it.
The key is shown once — copy it out of the dialog before you close it. A lost key is replaced, not recovered.
Alongside the key you need your client id — the mch_test_… or mch_live_…
value on the same page. It is not a secret; it names the account a request speaks
for. There is one per mode, and it has to match the key you pair it with: a
sandbox client id sent with a live key is refused.
3. Store the pair on your server
Put both values wherever your platform keeps secrets — environment variables, the plugin's encrypted settings table, a secrets manager. Every request sends them as headers:
X-Client-Id: mch_test_7fL2qXn4WbTzR9kD1sVyH6mCgA8eUpJ3
X-Api-Key: sk_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Keep the key server-side
The API key is a secret. Store it and use it only on your server — never in front-end JavaScript or anywhere else a browser can read it.
4. Register a webhook endpoint
Under Settings → Webhooks, add the URL on your store that should receive deliveries, and subscribe it to the events you care about. Endpoints are registered per mode, so a sandbox endpoint hears nothing about live orders.
The endpoint's signing secret is shown once, the same way the API key is. You need it to verify deliveries — see Signatures.
5. Confirm the connection
curl https://api.shotpay.com/api/v1/ping \
-H "X-Client-Id: $SHOTPAY_CLIENT_ID" \
-H "X-Api-Key: $SHOTPAY_API_KEY"
A 200 names the merchant the key resolved to and whether layaway is currently
available:
{
"data": {
"client_id": "mch_test_7fL2qXn4WbTzR9kD1sVyH6mCgA8eUpJ3",
"legal_name": "Frontier Firearms LLC",
"dba": "Frontier Range",
"key_prefix": "sk_test_a1b2",
"layaway": { "available": true, "reason": null, "message": null }
}
}
Anything other than a 200 is covered in
Error Handling.
Next: pick a client
Every endpoint is plain HTTP and stays callable directly. The parts worth not hand-writing — the checkout session lifecycle, your layaway contracts, and proving a delivery is genuine — are wrapped by the clients:
npm install @shotpay/node # server-side JS/TS client
npm install @shotpay/button # storefront button, holds no credentials
Both are on npm — @shotpay/node
and @shotpay/button. The PHP
client is not published yet. See SDK and
Button.