jadePOS API Reference
ทำให้ร้านทำงานอัตโนมัติ: สร้างรายการเก็บเงิน จัดการสินค้า อ่านบัญชี ยืนยันตัวตนด้วยกุญแจ API จากบัญชีของคุณ
Conventions
| Base URL | https://jadepos.store |
| Authentication | Authorization: Bearer jade_… — create and revoke keys under Account → API keys. Keys are stored hashed; the value is shown once. |
| Request bodies | application/x-www-form-urlencoded form fields (as in the curl examples) |
| Responses | JSON, application/json; charset=utf-8 |
| Amounts | Integers in minor units: 1250 = $12.50. JPY/KRW have no minor unit — pass whole yen/won. |
| Rate limits | Reads 60/min, product writes 60/min, charges 30/min (per IP). Exceeding answers 429 {"error":"rate_limited"}. |
| Errors | Non-2xx responses carry {"error":"human readable reason"} |
GET/api/v1/ping
Liveness check. The only endpoint that needs no key.
curl https://jadepos.store/api/v1/ping
→ {"ok":true,"service":"jadepos.store"}GET/api/v1/me
The merchant who owns the key — use it to verify a key and read your ledger currency.
curl -H "Authorization: Bearer jade_..." https://jadepos.store/api/v1/me
→ {"username":"demo","business_name":"Jade Cafe","currency":"USD"}GET/api/v1/products
Your full catalog, active and archived.
curl -H "Authorization: Bearer jade_..." https://jadepos.store/api/v1/products
→ {"products":[{"sku":"latte","name":"Latte","description":"Double shot",
"kind":"product","price_cents":450,"currency":"USD","tax_percent":8.5,
"requires_shipping":false,"active":true}]}POST/api/v1/products
Create a catalog item, or update it if the SKU already exists (upsert).
| Field | Description | |
|---|---|---|
| sku | required | Letters, digits, dot, dash, underscore; max 40. The upsert key. |
| name | required | Display name, max 120 chars. |
| price_cents | required | Integer minor units. |
| description | optional | Up to 500 chars. |
| kind | optional | product (default) or service. |
| currency | optional | Defaults to your ledger currency. |
| tax_percent | optional | Per-line tax rate, e.g. 8.5. Default 0. |
| requires_shipping | optional | 1 to demand a shipping address at checkout. Default 0. |
curl -X POST https://jadepos.store/api/v1/products \
-H "Authorization: Bearer jade_..." \
-d sku=beans-1kg -d "name=Coffee Beans 1kg" -d price_cents=1899 -d requires_shipping=1
→ {"ok":true,"sku":"beans-1kg","created":true}GET/api/v1/orders
Your orders, newest first, 50 per page. Draft carts are never included.
| Field | Description | |
|---|---|---|
| status | optional | paid, pending, declined, refunded, void; empty = all. |
| page | optional | 1-based page number. |
curl -H "Authorization: Bearer jade_..." "https://jadepos.store/api/v1/orders?status=paid&page=1"
→ {"orders":[{"ref":"JP-2524f49c22","status":"paid","total_cents":800,
"currency":"USD","customer_name":"Lin","created_at":"2026-08-27 09:12:44",
"paid_at":"2026-08-27 09:12:45"}]}GET/api/v1/transactions
The money ledger: one row per charge or refund attempt, newest first, 50 per page (page param). Card rows carry only the brand and last four digits — never the full number.
curl -H "Authorization: Bearer jade_..." https://jadepos.store/api/v1/transactions
→ {"transactions":[{"tx_ref":"TX-63505a62be6f","order_ref":"JP-e4a6c4dd8d",
"kind":"charge","method":"card","mode":"test","status":"approved",
"amount_cents":1250,"currency":"USD","card_brand":"amex",
"card_last4":"0005","auth_code":"F94FAC","created_at":"2026-08-26 16:04:46"}]}POST/api/v1/charges
Validate and charge a card, or record a PayPal / Cash App payment you already received. Creates a one-line order, charges it, and returns the outcome with a public receipt URL.
Common fields
| Field | Description | |
|---|---|---|
| method | required | card, paypal, or cashapp. Wallets must be enabled in Payments. |
| amount_cents | required | Positive integer minor units. |
| currency | optional | Defaults to your ledger currency. |
| description | optional | Line-item text on the order and receipt. |
| customer_name | optional | Shown on the order. |
| customer_email | optional | The receipt link is emailed when the mail watcher is configured. |
| ship_name … ship_country | optional | Shipping address: ship_name, ship_address1, ship_address2, ship_city, ship_region, ship_postal, ship_country. When ship_address1 is present the order gets a printable label at /label?ref=… (merchant login). |
Card fields (method=card)
| Field | Description | |
|---|---|---|
| card_number | required | Digits, spaces and dashes allowed. Never stored. |
| exp_month | required | 1–12. |
| exp_year | required | 4-digit (2030) or 2-digit (30). |
| cvv | required | 3 digits; 4 for American Express. Never stored. |
Wallet fields (method=paypal | cashapp)
| Field | Description | |
|---|---|---|
| reference | optional | Your note of the wallet payment (transaction id, screenshot ref). |
curl -X POST https://jadepos.store/api/v1/charges \
-H "Authorization: Bearer jade_..." \
-d method=card -d amount_cents=1250 -d currency=USD \
-d "description=Latte x2" \
-d card_number=4242424242424242 -d exp_month=12 -d exp_year=2030 -d cvv=123
→ 200 {"approved":true,"order_ref":"JP-1a2b3c4d5e","auth_code":"A1B2C3",
"card_brand":"visa","card_last4":"4242","amount_cents":1250,
"currency":"USD","receipt_url":"https://jadepos.store/receipt?ref=JP-1a2b3c4d5e"}
→ 402 {"approved":false,"order_ref":"JP-8f54674005","card_brand":"visa",
"error":"Card declined (test card)"}Whether a card charge is simulated (test) or sent to your processor (live) follows the card method's mode in Payments. The receipt URL is public but unguessable; it shows no card data beyond brand + last4.
Card validation
Every card is validated before any charge is attempted. A failure answers 402 with a reason and nothing is sent to the processor.
| Network | Detected by | Length | CVV |
|---|---|---|---|
| VISA Visa | 4… | 13, 16, 19 | 3 |
| Mastercard Mastercard | 51–55, 2221–2720 | 16 | 3 |
| DISCOVER Discover | 6011, 644–649, 65 | 16–19 | 3 |
| AMEX American Express | 34, 37 | 15 | 4 |
Plus the Luhn checksum and an expiry check against the current date. Other networks are rejected.
Test cards (test mode)
Any future expiry and matching-length CVV work with these:
| VISA | 4242 4242 4242 4242 | approved |
| MC | 5555 5555 5555 4444 | approved |
| DISC | 6011 1111 1111 1117 | approved |
| AMEX | 3782 822463 10005 | approved |
| VISA | 4000 0000 0000 0002 | declined |
Live card gateway relay
In live mode jadePOS POSTs each card charge as JSON to the HTTPS relay URL configured in Payments (loopback http://127.0.0.1 is also accepted for a relay on the same machine), with your relay key in the body:
{"api_key":"...","reference":"pre-...","amount_cents":1250,"currency":"USD",
"card_number":"...","exp_month":"12","exp_year":"2030","cvv":"..."}The relay must answer within ~20 seconds:
{"status":"approved","auth_code":"..."}
{"status":"declined","error":"..."}A ready-to-run relay for NMI and Authorize.net ships with the project: deploy/card_relay.py (Python stdlib, no installs) with deploy/relay_config.json choosing the processor and holding its credentials — they never enter jadePOS. It ships pointed at NMI's public sandbox until you swap in real keys; for Authorize.net, create free sandbox credentials at developer.authorize.net and set sandbox: true until go-live.
Status codes
200 | Success — including recorded declines on wallet endpoints; card declines use 402. |
400 | Malformed request: missing/invalid field, unknown method, bad SKU. |
401 | Missing, revoked, or wrong API key. |
402 | Card charge declined (validation failure or processor decline) — body carries approved:false and error. |
404 | Unknown route. |
429 | Rate limited — slow down and retry. |