Developer Portal
API documentation, integration guides, and webhook reference for building on the payment platform.
Quick Start
Integrate your CMS, website, or application with the checkout and licensing API in three steps:
Minimal Example (cURL)
curl -X POST https://pay.example.com/api/v1/stores/my-store/checkout/session/ \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"cart": {"WIN-11-PRO": 1}, "currency": "GBP"}'
Authentication
All authenticated API endpoints require a Store API Key passed in the Authorization header.
Authorization: Bearer <your_store_api_key>
API Key Types
| Type | Prefix | Use |
|---|---|---|
| Store API Key | sk_... |
Server-to-server: checkout sessions, licensing fulfillment |
| Public endpoints | None | Geo subdivisions, tax rates (no key required) |
Managing Keys
API keys are managed per-store in the Partner Portal under Stores → [Store] → API Keys. Keys are shown once on creation; store them securely. You can revoke a key at any time.
Security Best Practices
- Never expose API keys in client-side code or public repositories
- Use environment variables to store keys in your application
- Rotate keys regularly and revoke unused keys
- Use HTTPS for all API requests
API Reference
/api/v1/stores/<store_slug>/checkout/session/
Creates a signed checkout session and returns a URL to redirect customers to. This is the primary integration method for CMS and e-commerce platforms.
Request Headers
Authorization: Bearer <your_store_api_key> Content-Type: application/json
Request Body
{
"cart": {
"PRODUCT-SKU-1": 1,
"PRODUCT-SKU-2": 2
},
"currency": "GBP",
"locale": "en",
"metadata": {
"external_reference": "your-order-123",
"return_url_success": "https://your-site.com/success",
"return_url_cancel": "https://your-site.com/cancel"
}
}
Response (201 Created)
{
"token": "abc123...",
"checkout_url": "https://pay.example.com/s/your-store/cart/?token=abc123...",
"expires_at": "2026-03-02T12:00:00Z"
}
cURL
curl -X POST \
https://pay.example.com/api/v1/stores/my-store/checkout/session/ \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"cart": {"WIN-11-PRO": 1}, "currency": "GBP"}'
Python
import requests
resp = requests.post(
"https://pay.example.com/api/v1/stores/my-store/checkout/session/",
headers={"Authorization": "Bearer sk_live_..."},
json={
"cart": {"WIN-11-PRO": 1},
"currency": "GBP",
},
)
data = resp.json()
checkout_url = data["checkout_url"]
/api/v1/stores/<store_slug>/licensing/fulfill/
For licensing-only stores where payment is handled externally. Submit an external payment reference to allocate license keys.
Request Body
{
"customer_email": "[email protected]",
"items": [
{"sku": "PRODUCT-SKU", "quantity": 1}
],
"external_reference": "your-payment-id",
"currency": "GBP",
"total_minor": 2999
}
Response (201 Created)
{
"order_id": "ORD-ABC123",
"status": "fulfilled",
"items": [
{
"sku": "PRODUCT-SKU",
"license_keys": ["XXXXX-XXXXX-XXXXX-XXXXX"]
}
]
}
/api/v1/geo/subdivisions/?country=<ISO2>
Returns state/province/region subdivisions for a given country code. Useful for building address dropdowns.
Response Example (?country=US)
{
"country": "US",
"subdivisions": [
{"code": "AL", "name": "Alabama"},
{"code": "AK", "name": "Alaska"},
...
]
}
/api/v1/tax/rates/?country=<ISO2>
Returns applicable tax rates for a given country. Useful for pre-checkout price display.
Webhooks
Configure a webhook URL in your store settings to receive real-time order status notifications. Events are sent as POST requests with an HMAC signature for verification.
Available Events
| Event | Description |
|---|---|
order.created | New order created (payment initiated) |
order.fulfilled | Payment completed and keys allocated |
order.refunded | Order was refunded |
order.disputed | Chargeback/dispute opened |
Webhook Payload
{
"event": "order.fulfilled",
"order_id": "ORD-ABC123",
"external_reference": "your-ref-123",
"status": "fulfilled",
"total_minor": 2999,
"currency": "GBP",
"customer_email": "[email protected]"
}
Signature Verification (Python)
import hmac, hashlib
# Header: X-AnonymousPay-Signature: sha256=<hex_digest>
expected = hmac.new(
webhook_secret.encode(),
request.body,
hashlib.sha256
).hexdigest()
assert hmac.compare_digest(expected, signature)
Setup
- Go to Partner Portal → Store Settings → Payments & Commerce
- Enter your webhook URL (must be HTTPS in production)
- Set a webhook secret for signature verification
- Your server should respond with HTTP 200 within 10 seconds
Stripe Webhooks (Self-hosted / LAN)
If your instance is on a private network, use the Stripe CLI to forward events:
stripe listen --forward-to http://<your-host>:8000/stripe/webhook/ \
--events payment_intent.succeeded,charge.dispute.created,\
charge.dispute.updated,charge.dispute.closed,\
charge.dispute.funds_withdrawn,charge.dispute.funds_reinstated,\
charge.refunded
Integration Guides
Use the checkout session API to create a "Buy Now" button on your WordPress site.
// functions.php
add_action('wp_ajax_create_checkout', function() {
$response = wp_remote_post(
'https://pay.example.com/api/v1/stores/my-store/checkout/session/',
[
'headers' => [
'Authorization' => 'Bearer ' . EPAY_API_KEY,
'Content-Type' => 'application/json',
],
'body' => json_encode([
'cart' => ['SKU-001' => 1],
'currency' => 'GBP',
]),
]
);
wp_send_json(json_decode(wp_remote_retrieve_body($response)));
});
Server-side: create a checkout session via API. Client-side: redirect to the returned URL.
// Node.js / Express
app.post('/buy', async (req, res) => {
const resp = await fetch(
`${EPAY_URL}/api/v1/stores/${STORE}/checkout/session/`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
cart: req.body.cart,
currency: 'GBP',
}),
}
);
const { checkout_url } = await resp.json();
res.redirect(checkout_url);
});
For simple integrations, use direct add-to-cart links with no server-side code required:
<!-- Single product --> <a href="/s/my-store/cart/?add=SKU-001¤cy=GBP"> Buy Now </a> <!-- Multiple products --> <a href="/s/my-store/cart/?items=SKU1:1,SKU2:2¤cy=GBP"> Buy Bundle </a>
List your products on the shared marketplace at /market/. Manage listings from the Marketplace tab in your partner portal. Customers browse, add to cart, and checkout — attribution is automatic.
Rate Limits
| Endpoint | Auth | Rate Limit |
|---|---|---|
| Checkout Session | Bearer sk_... |
100 req/min per key |
| Licensing Fulfill | Bearer sk_... |
100 req/min per key |
| Geo Subdivisions | None | 300 req/min per IP |
| Tax Rates | None | 300 req/min per IP |
All API responses include X-RateLimit-Remaining and X-RateLimit-Reset headers. If you hit the limit, the API returns HTTP 429 with a Retry-After header.
Error Responses
| Code | Meaning |
|---|---|
400 | Bad request (invalid JSON, missing fields) |
401 | Unauthorized (missing or invalid API key) |
404 | Store or product not found |
429 | Rate limit exceeded |
500 | Internal server error |