Getting Started
Two calls: start Light KYC with the buyer’s identity, then create a payment and redirect to hosted checkout. Phone, address and birthdate belong on KYC start only.
API Access
Create a sandbox key (sdk_…) in the merchant portal after registration. Live keys (pk_…) activate after KYB approval.
https://stixpay.com
Send X-API-Key on every request. Environment comes from the key prefix — do not send a sandbox body flag.
| Key | Use |
|---|---|
sdk_… | Test — KYC auto-approved, Test Gateway only |
pk_… | Live — production KYC + providers |
secret_… | Webhook signing only (not an API key) |
Try it in the API Console. Full schema: openapi.yaml.
How a payment works
-
1
POST /api/kyc/start— create the customer and start Light KYC (auto-approved withsdk_…). -
2
POST /api/payment/create— samecustomer_email+ payment fields. Receiveredirect_url. -
3
Redirect the buyer to
redirect_url(hosted checkout). -
4
Listen for
payment.succeeded/payment.failed, or pollGET /api/payment/{payment_id}/status.
KYC is per customer (shared across merchants) and must be approved on the same key plane (sandbox vs live). Without Light KYC approved, create payment returns HTTP 422 kyc_required. Sandbox KYC does not affect the live profile.
1 — Start KYC
Creates the StixPay customer if needed and starts Light KYC. Send all identity fields here.
Body
| Field | Description |
|---|---|
customer_email | Buyer email |
customer_first_name | First name |
customer_lastname | Last name |
customer_phone | E.164, e.g. +33611223344 |
birthdate | YYYY-MM-DD |
customer_address | Street address |
postal_code | Postal / ZIP |
city | City |
country | ISO alpha-2, e.g. FR, US. USA is normalized to US. |
customer_state | US state — required when country is US (or USA). 2-letter code, e.g. CA, NY. Aliases: state, state_of_residence. |
level | light |
Request
POST /api/kyc/start
Content-Type: application/json
X-API-Key: sdk_your_test_key
{
"customer_email": "[email protected]",
"customer_first_name": "Jane",
"customer_lastname": "Doe",
"customer_phone": "+33611223344",
"birthdate": "1990-01-15",
"customer_address": "1 rue de Rivoli",
"postal_code": "75001",
"city": "Paris",
"country": "FR",
"level": "light"
}
Response (sandbox)
HTTP 200
{
"success": true,
"already_approved": true,
"customer_user_id": 1842,
"customer_created": true,
"kyc_state": "verified_light",
"set_password_url": "https://stixpay.com/customer/set_password.php?token=…",
"environment": "test"
}
For US buyers, include a state code (customer_state, state, or state_of_residence) — e.g. "country": "US", "customer_state": "CA".
New customers get a set-password link by email; hosted checkout can also finish password setup.
Poll KYC: GET /api/kyc/[email protected]
2 — Create payment
Same API key plane as KYC start. Returns payment_id + redirect_url. Do not send phone, address, postal code, city or birthdate.
Body
| Field | Description |
|---|---|
amount | Amount > 0 |
currency | e.g. EUR |
payment_method | Optional. How the buyer pays on hosted checkout (card, Apple Pay, bank transfer, …). Alias: checkout_payment_method. Default: credit_card. See values below. Do not send with product_id (NFT). |
merchant_order_id | Unique per merchant |
customer_email | Same email as KYC start |
store_name | Store label |
success_url | Absolute URL |
failure_url | Absolute URL |
provider_code | Optional. Lock the on-ramp rail (wert, banxa_api, banxa_hosted, transak_api, …). |
payment_method — what it does
It tells StixPay which checkout rail to open for the buyer (card form, Apple Pay, SEPA, PayPal, …). It is independent of KYC. Availability still depends on the on-ramp provider, the buyer’s country/currency, and methods enabled for your merchant.
| Value | Meaning |
|---|---|
credit_card | Debit / credit card (default) |
apple_pay | Apple Pay |
google_pay | Google Pay |
open_banking | SEPA / open banking transfer |
paypal | PayPal |
ideal | iDEAL (NL) |
sofort | Sofort |
klarna_paynow | Klarna Pay Now |
gbp_bank_transfer | GBP bank transfer |
ach_bank_transfer | ACH bank transfer (US) |
payid_bank_transfer | PayID bank transfer (AU) |
npp_bank_transfer | NPP bank transfer (AU) |
interac | Interac (CA) |
pix | Pix (BR) |
spei | SPEI (MX) |
khipu | Khipu |
zar_bank_transfer | ZAR bank transfer (ZA) |
pse | PSE (CO) |
vietqr | VietQR / QR wallet |
Common aliases are accepted (e.g. card → credit_card, sepa → open_banking). If omitted or empty, StixPay uses credit_card.
Request
POST /api/payment/create
Content-Type: application/json
X-API-Key: sdk_your_test_key
{
"amount": 19.99,
"currency": "EUR",
"payment_method": "credit_card",
"merchant_order_id": "ORDER_123",
"customer_email": "[email protected]",
"store_name": "Example Store",
"success_url": "https://shop.example/success",
"failure_url": "https://shop.example/failed"
}
Response
HTTP 200
{
"success": true,
"payment_id": "9021",
"merchant_order_id": "ORDER_123",
"redirect_url": "https://stixpay.com/customer/checkout.php?token=…",
"expires_at": "2026-09-01 10:00:00"
}
Redirect the buyer to redirect_url.
If KYC is missing
HTTP 422
{
"success": false,
"error": "kyc_required",
"message": "Customer Light KYC is not approved for the test (sandbox) environment…"
}
Payment status
- pending — created; buyer has not finished checkout
- pending_topup — on hosted checkout / paying
- succeeded — paid (
payment.succeeded) - failed — not paid (
payment.failed) - expired — not completed in time
Lookups (GET)
All require X-API-Key except health.
Opaque KYC state for a customer you started. Query: customer_email (or customer_user_id).
GET /api/kyc/[email protected] X-API-Key: sdk_your_test_key
Full payment object for a payment_id returned by create payment.
Lightweight status for polling after redirect.
Paginated list. Query: page, per_page, status, q (search order id / email / payment id).
Merchant balance breakdown (available / hold / reserve, EUR).
Indicative FX quote. Query: amount, currency (required).
GET /api/quote?amount=19.99¤cy=EUR X-API-Key: sdk_your_test_key
Reference FX rate table.
Public platform status (no API key).
Webhooks
Register your URL in Merchant → Webhooks and select the events to receive. Verify X-Webhook-Signature (HMAC-SHA256 of the raw body with your secret_…). Respond with HTTP 200.
Envelope: { id, type, created, data }.
Payments & KYC
| Event | When |
|---|---|
customer.kyc.updated | Customer Light KYC state changed |
payment.succeeded | Payment completed |
payment.failed | Payment failed |
payment_intent.canceled | Payment cancelled before completion |
refund.completed | Refund completed |
Payouts
| Event | When |
|---|---|
payout.completed | Merchant payout to your bank / crypto wallet completed |
payout.failed | Merchant payout failed |
transaction_payout_success | On-ramp settlement / USDC payout for a paid transaction succeeded |
Test delivery: POST /api/webhook/test or “Send test” in the portal.