ระบบขายหน้าร้านที่ปลอดภัย — ทุกบัญชีได้รับการปกป้องด้วยการยืนยันตัวตนสองขั้นตอน
jadePOSจุดขาย

jadePOS API Reference

ทำให้ร้านทำงานอัตโนมัติ: สร้างรายการเก็บเงิน จัดการสินค้า อ่านบัญชี ยืนยันตัวตนด้วยกุญแจ API จากบัญชีของคุณ

ConventionsGET /pingGET /meGET /productsPOST /productsGET /ordersGET /transactionsPOST /chargesCard validationTest cardsGateway relayStatus codes

Conventions

Base URLhttps://jadepos.store
AuthenticationAuthorization: Bearer jade_… — create and revoke keys under Account → API keys. Keys are stored hashed; the value is shown once.
Request bodiesapplication/x-www-form-urlencoded form fields (as in the curl examples)
ResponsesJSON, application/json; charset=utf-8
AmountsIntegers in minor units: 1250 = $12.50. JPY/KRW have no minor unit — pass whole yen/won.
Rate limitsReads 60/min, product writes 60/min, charges 30/min (per IP). Exceeding answers 429 {"error":"rate_limited"}.
ErrorsNon-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).

FieldDescription
skurequiredLetters, digits, dot, dash, underscore; max 40. The upsert key.
namerequiredDisplay name, max 120 chars.
price_centsrequiredInteger minor units.
descriptionoptionalUp to 500 chars.
kindoptionalproduct (default) or service.
currencyoptionalDefaults to your ledger currency.
tax_percentoptionalPer-line tax rate, e.g. 8.5. Default 0.
requires_shippingoptional1 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.

FieldDescription
statusoptionalpaid, pending, declined, refunded, void; empty = all.
pageoptional1-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

FieldDescription
methodrequiredcard, paypal, or cashapp. Wallets must be enabled in Payments.
amount_centsrequiredPositive integer minor units.
currencyoptionalDefaults to your ledger currency.
descriptionoptionalLine-item text on the order and receipt.
customer_nameoptionalShown on the order.
customer_emailoptionalThe receipt link is emailed when the mail watcher is configured.
ship_name … ship_countryoptionalShipping 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)

FieldDescription
card_numberrequiredDigits, spaces and dashes allowed. Never stored.
exp_monthrequired1–12.
exp_yearrequired4-digit (2030) or 2-digit (30).
cvvrequired3 digits; 4 for American Express. Never stored.

Wallet fields (method=paypal | cashapp)

FieldDescription
referenceoptionalYour 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.

NetworkDetected byLengthCVV
VISA Visa4…13, 16, 193
Mastercard Mastercard51–55, 2221–2720163
DISCOVER Discover6011, 644–649, 6516–193
AMEX American Express34, 37154

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:

VISA4242 4242 4242 4242approved
MC5555 5555 5555 4444approved
DISC6011 1111 1111 1117approved
AMEX3782 822463 10005approved
VISA4000 0000 0000 0002declined

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

200Success — including recorded declines on wallet endpoints; card declines use 402.
400Malformed request: missing/invalid field, unknown method, bad SKU.
401Missing, revoked, or wrong API key.
402Card charge declined (validation failure or processor decline) — body carries approved:false and error.
404Unknown route.
429Rate limited — slow down and retry.