Skip to main content
A terminal is a card reader that Payra assigns to your account. Your server sends a payment to it, the customer presents the card there, and the payment then behaves like any other: you read it back, receive its webhooks and refund it. Calls to the API always come from your server. Never put a secret key on a tablet or phone that sits next to the terminal: have it ask your server, and have your server call Payra. Terminal endpoints, including check-out and check-in, use the terminals:read and terminals:write scopes; sending and canceling a payment use the payments scopes.

Find a terminal

Response
  • Only terminals that are assigned to your account and ready to take payments are listed, in the key’s environment. A terminal still being set up, moved to another account or retired is not listed, and GET /terminals/{id} answers it 404 resource_missing.
  • label and serial_number are exact filters, applied before starting_after. Neither is unique, so a filter can return more than one terminal.
  • Unlike most lists, this one runs oldest first. It takes limit from 1 to 100 (default 20), starting_after and has_more as described in Pagination. One more difference: a starting_after whose terminal was retired or moved since the last page still continues after it, so a long walk does not stall.
  • model and serial_number come from the hardware; the serial number is printed on the back of the terminal. label is your name for the terminal, null until you give it one.
  • The id does not change when you rename the terminal. Pass it as terminal on a payment.
  • checked_out_to and checked_out_at say who has the terminal right now, when you share payment devices; null while it sits free.

Name a terminal

The name is 1 to 120 characters, and it also shows in RevOS and in the Virtual Terminal. null removes it: the API then shows label: null, and RevOS goes back to the terminal’s default name. A name equal to one of the terminal’s own identifiers, such as its serial number, reads back as null too.

Send a payment to a terminal

The answer is 201 with a processing payment: the terminal shows the amount and waits for the card. See Terminal payments for the request rules and the payment it returns.
  • Follow it with GET /payments/{id}, no faster than every 5 seconds, or with the webhooks. It ends succeeded, failed or canceled.
  • One payment per terminal at a time. A second payment to a terminal still on one answers 400 terminal_busy and creates nothing, so the same Idempotency-Key works once the terminal is free. If you are unsure whether a payment went through, read it back before sending it again: a new payment with a new key, sent after the first one finished, is a second charge.
  • Cancel with POST /payments/{id}/cancel while the terminal waits for the card. Once the card is presented it is too late (400 payment_not_cancelable), and the payment finishes on its own. A 409 conflict means the cancel could not be confirmed (the terminal’s answer was lost, or the payment changed while the cancel ran): the payment was not canceled, so retry the cancel.
  • Nobody pays: after five minutes without a card the payment is canceled with cancellation_reason: "expired". If the terminal does not confirm that cancel, the payment stays processing while Payra retries.
  • A lost answer: if Payra loses the processor’s answer when it sends the payment, or the processor fails with a server error, the payment stays processing until Payra learns the outcome. It does not expire, cannot be canceled through the API, and the terminal refuses new payments with terminal_busy until then. Contact support if it lasts.
  • Refund it with POST /refunds, as any other payment.

Share payment devices

A few terminals can serve many tablets, trucks or people: a plant keeps its terminals on a charging shelf, and whoever needs one for the day takes it and brings it back. Payra keeps track of who has which, so your app does not have to.
  • Terminals belong to your account, not to a device. Any tablet may send a payment to any of your terminals; what ties a terminal to a tablet for the day is the check-out below.
  • Give each terminal a fixed name (POST /terminals/{id} with a label, say the name on its sticker) and keep it. The check-out, not the name, says who has it, so nothing is renamed as terminals change hands.
  • One payment per terminal at a time, as always: a second payment to a terminal still on one answers terminal_busy. A check-out does not change that; a checked-out terminal takes payments as before.

Check a terminal out

Response
  • checked_out_to is your name for who takes it, 1 to 120 characters: a tablet, a truck, a driver. It shows in RevOS next to the terminal.
  • checked_out_by is optional: your own user doing the check-out, such as the driver or dispatcher signed in to your app. Payra keeps it in the terminal’s check-out history for your audit.
  • A terminal checked out to someone else since the last nightly release answers 400 terminal_checked_out, and the error carries checked_out_to naming who has it. Of two apps checking the same terminal out at the same moment, one gets the terminal and the other this error, so pick again from the free ones. Nothing changes on a refusal, so the same Idempotency-Key works once the terminal is free.
  • A check-out to whoever already has the terminal since the last nightly release answers 200 as it is, so a request whose answer was lost can be sent again.
  • "replace": true takes the terminal over from whoever has it instead of that error, for a check-in someone forgot since the last nightly release. Send it only when you know the terminal is in hand: a replace on a terminal still out in a truck leaves Payra saying the wrong person has it.
  • Without replace, a check-out still open from before the last nightly release (2 AM in your account’s time zone) is released first, with end_reason nightly_release, and the terminal is checked out to you, whoever had it. See A day on the shelf.

Find a free terminal

checked_out=false lists the terminals nobody has; checked_out=true the ones out, and checked_out_to=Tablet%20TB0011 the ones a given tablet has. When the names carry the plant, as in PAY101801 for plant 1018, label_prefix=PAY1018 narrows the list to that plant, so ?label_prefix=PAY1018&checked_out=false is “a free terminal at plant 1018”. All of these are filters on the terminal list, applied before starting_after. The plant lives only in the name: renaming PAY101801 to Truck 575 moves it out of that filter, so keep the names fixed and let the check-out say who has the terminal. A terminal reads checked_out_to: null and checked_out_at: null while it sits free.

Check it back in

  • The answer is the terminal, free again. A terminal that was already free answers 200 as it is.
  • checked_out_to is optional. When you send it, the check-in only goes through if that is who has the terminal; otherwise it answers 400 terminal_checked_out and nothing changes. Send it from the device returning the terminal, so a late check-in cannot free a terminal someone else took since. Leave it out from an admin screen that frees a terminal whoever has it.
  • checked_in_by is optional, your user doing the check-in, kept in the history.

Read the history

Response
  • One row per check-out, newest first. The first row is the current one while its checked_in_at is null.
  • end_reason says how a check-out ended: check_in; replaced, when a check-out with replace took the terminal over; nightly_release, when Payra freed it because it was still out from before the last 2 AM (see A day on the shelf), with checked_in_by set to Payra; dashboard_check_in, when one of your users checked it in from RevOS, with checked_in_by set to their name; unassigned, when Payra took the terminal off your account; or transferred, when Payra moved it to another account. Either of the last two ends the check-out with it. More values may be added, so treat one you do not recognize as an ended check-out.
  • The history lists your account’s check-outs and is readable while the terminal is assigned to your account; otherwise it answers 404 resource_missing, like the terminal itself.
  • limit 1 to 100 (default 20) and starting_after page it as in Pagination.

A day on the shelf

  1. At clock-in, your app lists GET /terminals?checked_out=false, picks one and checks it out to the tablet. It tells the driver which terminal to grab, by its name.
  2. During the day, the tablet sends payments with that terminal’s id.
  3. At clock-out, the tablet checks it in with its own checked_out_to. If the driver forgot, an admin screen checks it in without checked_out_to, someone who manages devices checks it in from Devices in RevOS, or the next check-out sends "replace": true once someone has confirmed the terminal is back on the shelf. Without replace, a new check-out of a terminal someone has had since the last nightly release answers terminal_checked_out.
  4. Every night Payra checks in any terminal still checked out from before 2 AM in your account’s time zone (US Central when none is set; 3 AM on the night clocks spring forward), so each day starts with every terminal free. The hourly release does it at 2 AM in every US time zone (within the hour after 2 AM in half-hour zones such as Newfoundland), or at the next hour if a run is late, and a check-out that finds such a terminal first frees it then. A terminal checked out after 2 AM is left alone.
  5. A terminal Payra takes off your account or moves to another account leaves the list; its check-out ends with it.