One merchant's own POS or software
How do I connect my own POS or back office to my card reader?
- For
- A merchant, or a developer working for one merchant.
- Key
- The merchant's own key (m360_live_…).
M360-On-Behalf-Of header.Create the key
RequiredOnceIn Merchant360 → Developers, create a live key with only the scopes the software needs (for card readers: terminal:read, payments:read, payments:write). Keep it on a server or in protected settings, never in a web page or a shipped app.
Build against the sandbox
RequiredBefore go-liveA free m360_test_ key from the sandbox: any terminal_id works, the sale approves on GET /payments/{id}, and no money moves.
Find your readers
RequiredOnce, and when a reader changesGET /terminal/devices lists the readers; save which terminal_id is at which station.
Send the sale to the reader
RequiredEvery salePOST /payments with the amount in cents and the terminal_id of the reader at that station. Merchant360 hands the sale to that reader: it leaves its waiting screen, shows the amount and asks for the card (tap, chip or swipe). Card data never reaches your software.
Always send terminal_id: it is how Merchant360 knows which reader to wake. Left out, the sale goes to the merchant’s default reader, which is wrong for a store with two stations.
You get 202 at once, with status: "pending" and a payment id starting tp_. Save the id.
POST /payments
Authorization: Bearer m360_live_…
Idempotency-Key: T-1001
{ "amount": 1800, "terminal_id": "PAXA35/2290000001", "invoice_number": "T-1001" }
202 { "id": "tp_5b0e…", "object": "payment", "status": "pending", "amount": 1800 }Get the result
RequiredEvery saleAsk for the payment every 2 to 3 seconds until its status is no longer pending:
succeeded: approved.amountis what was charged (with any tip or fee the merchant’s pricing adds on the reader);cardhas the brand and last 4.failed: declined.canceled: cancelled on the reader, or by you.
A sale is never cancelled on a timer. One still pending after 360 seconds is flagged for review and stays pending.
GET /payments/tp_5b0e…
200 { "id": "tp_5b0e…", "status": "succeeded", "amount": 1800,
"card": { "brand": "VISA", "last4": "4242" } }Cancel, void, refund, tip
RequiredWhen the clerk asksPOST /payments/{id}/cancel: stop a sale still waiting for the card. If the card was charged just before, it is voided.POST /payments/{id}/void: undo an approved sale the same day, before the batch closes.POST /payments/{id}/refund: money back after the batch closed. Sendamountfor part of it.POST /payments/{id}/tip-adjust: add or change a tip on an approved sale.
Handle a lost answer
RequiredEvery POSTSend an Idempotency-Key (your order or ticket id) on every POST. If the answer is lost (timeout, restart, Wi-Fi drop), send the same POST again with the same key: you get the same payment back, never a second sale. Then read its status as in the previous step.
Per-sale options
OptionalAny saleterminal_options.allow_cancel: false: no Cancel Sale button on the reader for this sale.terminal_options.print_receipt: true: the reader prints or offers the receipt for this sale, for a register with no printer.false: your POS prints and the reader goes back to its waiting screen. Left out: the terminal’s setting (Payment App 2.46.4 or later).terminal_options.allow_keyed: true: a Key enter card button, for a card that will not read. Needs keyed (MOTO) sales on the merchant; the reader then asks for CVV, ZIP and street number by default.tip: { prompt: true }: the tip screen on the reader.POST /payments/authorizewith the same body: a hold instead of a sale, captured later with/payments/{id}/captureor released with/void. Needs pre-auth on the merchant.
Get results pushed to you
OptionalOncePOST /webhooks with your HTTPS URL. Same benefits as for an ISV: results your POS missed, and refunds or voids done elsewhere.
Show the error code
RequiredAny refused callEvery error is { "error": { "message", "code" } }. Most refusals name a setting, not an outage: show the code to your user instead of “contact support”.
403 no_grant: the merchant is not connected to you.403 insufficient_scope: your key is not granted that kind of call.403 billing_tools_off: the merchant’s Billing Tools are off.403 not_permitted_by_channel: reports or refunds are off for partners on that merchant.409 terminal_unavailable: no card readers on the account.422 moto_not_enabled/422 preauth_not_enabled: keyed sales / pre-auth are off for the merchant.429 rate_limited: too many requests in the minute.500: ours. Send us the time and your reference.