Quick Start
Make your first live-shaped request in under five minutes. Every Koi Pay API call is an HTTPS POST or GET to the gateway, authenticated with your secret key, carrying a JSON body and returning a JSON envelope.
1. Get your keys
From the portal, open Settings → API keys. You'll find a sandbox secret key for testing and a live secret key for production. Treat both like passwords — they authorize money movement.
2. Send a sale
Charge a card by posting a sale to the Transactions endpoint. Amounts are always in cents, so $10.00 is 1000.
# charge $10.00 to a test card curl https://sandbox.example.com/api/transaction \ -H "Authorization: YOUR_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "sale", "amount": 1000, "payment_method": { "card": { "number": "4111111111111111", "expiration": "12/29", "cvc": "123" } } }'
3. Read the response
Every response is the same envelope: a status, a human-readable msg, and a data object with the details.
{
"status": "success",
"msg": "Approved",
"data": {
"id": "txn_8Fp2k9",
"response_code": 100,
"amount": 1000,
"auth_code": "A1B2C3",
"card": { "last4": "1111", "brand": "visa" }
}
}
4. Go live
When you're ready, swap the sandbox host for your production host and the sandbox key for your live key. Nothing else changes — the contract is identical between environments.
Integration paths
There's more than one way to embed Koi Pay. Pick the path that matches how much of the payment surface you want to own.
| Path | Best for | PCI scope |
|---|---|---|
| Tokenizer / WalletJS (client-side) | Web checkouts that want full design control with no card data touching your server | Lowest (SAQ A) |
| Simple Payments (hosted) | Fastest launch — a hosted, brandable payment page or button | Lowest (SAQ A) |
| Direct API (server-side) | Platforms processing card-present, MOTO or stored credentials end-to-end | Higher (SAQ D) |
| Plugins (WooCommerce, Magento, Gravity Forms) | Existing storefronts that want a drop-in extension | Lowest (SAQ A) |
| Gateway Emulator | Migrating merchants off a legacy gateway with no rewrite | Matches existing |
Authentication
Authenticate every request with your secret key in the Authorization header. There is no Bearer prefix — send the key directly.
Authorization: YOUR_SECRET_KEY Content-Type: application/json
Request conventions
- All requests and responses use
Content-Type: application/json. - Amounts are integers in cents.
$25.50is sent as2550. - Every response shares the same envelope:
{ "status", "msg", "data" }. statusis"success"or"error"; the numeric processor result lives indata.response_code.- Timestamps are ISO 8601 in UTC. IDs are opaque strings — don't parse them.
Transactions
The Transactions API moves money: authorize, capture, sale, refund and void. Send a type and the gateway routes it to the processor.
| Type | What it does |
|---|---|
authorize | Reserve funds without capturing — finalize later with a capture. |
capture | Settle a previous authorization, in full or partial. |
sale | Authorize and capture in one step. |
refund | Return funds for a settled transaction. |
void | Cancel an authorization or unsettled sale. |
{
"type": "sale",
"amount": 4999,
"payment_method": { "customer_vault_id": "cv_72ab" }
}
// 1) reserve the funds { "type": "authorize", "amount": 4999, "payment_method": { "card": { "number": "4111111111111111", "expiration": "12/29" } } } // 2) capture later, by transaction id { "type": "capture", "transaction_id": "txn_8Fp2k9", "amount": 4999 }
{
"type": "refund",
"transaction_id": "txn_8Fp2k9",
"amount": 4999
}
Level 3 data
For B2B and B2G cards, attach line-item detail to qualify for the lowest interchange. Koi Pay assembles the Level 3 fields for you — pass the items and we format the rest.
Customer Vault
Store cards and bank accounts as tokens so you never re-handle raw credentials. Vault records are referenced by customer_vault_id anywhere a payment method is accepted.
| Operation | Endpoint |
|---|---|
| Create record | POST /api/vault with "action":"add" |
| Update record | POST /api/vault with "action":"update" |
| Delete record | POST /api/vault with "action":"delete" |
{
"action": "add",
"customer": { "first_name": "Ada", "email": "ada@acme.co" },
"payment_method": { "card": { "number": "4111111111111111", "expiration": "12/29" } }
}
Recurring Billing
Define a plan, attach a customer (typically a vault record), and the gateway charges on schedule — with retries, proration and dunning handled for you.
{
"plan": {
"amount": 2900,
"interval": "month",
"day_of_month": 1
},
"customer_vault_id": "cv_72ab",
"start_date": "2026-07-01"
}
| Field | Notes |
|---|---|
interval | day, week, month or year. |
amount | Per-cycle charge in cents. |
start_date | First billing date; omit to start immediately. |
trial_days | Optional free trial before the first charge. |
Invoices
Create, send and track invoices. Each invoice generates a hosted, brandable pay link your customer can settle by card or ACH.
{
"customer": { "email": "ada@acme.co" },
"items": [ { "description": "Design retainer", "amount": 150000 } ],
"due_date": "2026-07-15",
"send": true
}
Batch
Submit many transactions in a single request for high-volume billing runs. The gateway processes the batch and returns a per-row result set you can reconcile against.
{
"transactions": [
{ "type": "sale", "amount": 1000, "customer_vault_id": "cv_72ab" },
{ "type": "sale", "amount": 2500, "customer_vault_id": "cv_91cd" }
]
}
BIN Lookup
Identify a card's brand, type, issuing bank and country from its first digits — before you authorize. Use it to route smarter, screen risk, or surface fees.
{
"status": "success",
"data": {
"brand": "visa",
"type": "credit",
"issuer": "Example Bank",
"country": "US"
}
}
Settlement Batches
Inspect every settlement batch and its line items. Reconcile deposits, fees and refunds against your ledger, and offer same-day (T+0) payout visibility.
{
"data": {
"batch_id": "set_20260622",
"funded_amount": 482310,
"fees": 11240,
"transactions": 214
}
}
Terminals
Provision, pair and send transactions to card-present (EMV) terminals. Push an amount to a registered terminal and collect a chip, tap or swipe.
{
"terminal_id": "trm_4410",
"amount": 3200
}
Custom Fields
Attach your own metadata to transactions, customers and invoices — order IDs, location codes, sales-rep tags — and filter or report on them later in the portal and API.
{
"type": "sale", "amount": 1000,
"custom_fields": { "order_id": "A-8841", "location": "store-12" }
}
Cart
Build server-side carts with itemized lines, tax and shipping, then hand off to checkout. Cart data flows into Level 3 detail and receipts automatically.
{
"items": [ { "sku": "TEE-01", "qty": 2, "unit_price": 1800 } ],
"tax": 300, "shipping": 500
}
Tokenizer
A drop-in JavaScript library that turns card fields into single-use tokens in the browser, so raw card data never touches your server and your PCI scope stays at SAQ A. Style the iframe fields to match your checkout.
<!-- 1) drop in the library with your PUBLIC key --> <script src="https://sandbox.example.com/tokenizer/tokenizer.js" data-public-key="YOUR_PUBLIC_KEY"></script> <!-- 2) mount the secure card field --> <div id="koi-card"></div>
// returns a one-time token you POST to your server KoiTokenizer.tokenize().then(function(t) { fetch("/charge", { method: "POST", body: JSON.stringify({ token: t.token }) }); });
On your server, charge the token exactly like a card via the Transactions API by passing "payment_method": { "token": "..." }.
Simple Payments
The fastest way to get paid: a hosted, fully brandable payment page or button with no front-end build. Create a payment link, share it, get notified by webhook when it's paid.
{
"amount": 5000,
"description": "Deposit — Order A-8841",
"redirect_url": "https://yourshop.com/thanks"
}
Webhooks
Subscribe to events and the gateway POSTs a signed JSON payload to your endpoint. Delivery is idempotent — verify the signature, ack with 200, and dedupe on the event id.
| Event | Fires when |
|---|---|
transaction.approved | A sale or capture succeeds. |
transaction.declined | A charge is declined by the issuer. |
settlement.funded | A settlement batch is funded. |
vault.updated | A stored card is refreshed by Account Updater. |
recurring.charged | A recurring cycle is billed. |
{
"id": "evt_5kP1",
"event": "transaction.approved",
"data": { "id": "txn_8Fp2k9", "amount": 1000 }
}
Fraud Protection — Koi Guard™
Rules, velocity filters and ML scoring tuned per merchant, not generic internet traffic. Configure sensitivity per MID, opt into network-wide Community Rules, and review held transactions in the portal.
- Rules & velocity — block or hold by amount, BIN, geo, AVS/CVV result, or attempt frequency.
- ML scoring — every transaction gets a risk score; you choose the threshold to hold or decline.
- Community Rules — a coordinated attack on one merchant becomes a shield for the whole portfolio.
WalletJS
Add Apple Pay and Google Pay to any checkout with a single script. WalletJS handles the wallet sheet, decrypts the network token, and returns a Koi Pay token you charge like any other.
<script src="https://sandbox.example.com/wallet/wallet.js"></script> <div id="koi-wallet" data-amount="1000"></div>
Fee programs
Pass on the cost of acceptance compliantly. Configure per merchant; the gateway applies the program at authorization and discloses it on receipts.
| Program | How it works |
|---|---|
| Cash Discount | Patented DTI model that holds up across card-present, online and virtual terminal. |
| Dual Pricing | Show a cash price and a card price at the POS, difference handled and disclosed automatically. |
| Surcharging | Compliant credit-card surcharging with caps, disclosures and exemptions enforced by the gateway. |
Integration workflows
A typical embedded checkout stitches a few APIs together. Here's the canonical flow for a tokenized web payment with a stored customer.
Tokenize
Tokenizer turns card fields into a one-time token in the browser.
Vault
Optionally store the token in the Customer Vault for reuse.
Charge
POST a sale to the Transactions API with the token or vault id.
Confirm
Receive a webhook, reconcile the settlement batch, and fulfill.
E-Commerce plugins
Drop Koi Pay into an existing storefront with a maintained extension — no API code required. See Integrations for install guides.
WooCommerce
WordPress checkout, subscriptions and refunds, powered by the Tokenizer for SAQ A scope.
Magento / Adobe Commerce
Native payment method with vault, capture and partial refund support.
Gravity Forms
Take one-time and recurring payments directly from any Gravity Form.
Testing
Point your integration at the sandbox host and use the test keys from your portal. No real money moves; responses mirror production exactly.
https://sandbox.example.com
Test cards
| Card number | Result | Code |
|---|---|---|
4111 1111 1111 1111 | Approved | 100 |
4000 0000 0000 0002 | Declined | 200 |
4000 0000 0000 9995 | Insufficient Funds | 200 |
4000 0000 0000 0051 | Partial Approval | 100 |
Use any future expiration date and any 3-digit CVC. You can also run the same scenarios live in the portal's virtual terminal.
Quick reference
Required headers
| Header | Value |
|---|---|
Authorization | YOUR_SECRET_KEY (no Bearer prefix) |
Content-Type | application/json |
Conventions
- Amounts are integers in cents.
- Every response is
{ "status", "msg", "data" }.
Response codes
| Code | Meaning |
|---|---|
| 100 | Approved |
| 200 | Declined |
| 201 | Declined — call issuer |
| 300 | Gateway error |