Skip to main content

Approvals

Some outlets ask a manager to approve a return, a refund or an exchange. The manager proves it with a PIN or a one-time code. You then send the approval_token you got with the return, refund or exchange. See Returns, Refunds and Exchanges.

All approval calls need X-Outlet-ID and X-User-ID, and the acting user's role must allow verifying approvals (the same permission the cashier app checks). The PIN and one-time code calls also need the user to have an open shift at the outlet, otherwise they answer 409 SHIFT_NOT_OPEN. GET /approvals/eligible-approvers is a read and needs no open shift. Approval calls take no Idempotency-Key.

When Approval Is Needed​

Each outlet decides, for each type (refund, return, exchange, order_cancel), whether an approval is needed and how it is given. A return, refund or exchange sent without a token answers 403 APPROVAL_REQUIRED when approval is needed. When it is not needed, the token is not required.

Check first with GET /approvals/eligible-approvers?types=refund (a comma list, for example types=refund,return):

  • is_enabled is false: no approval is needed. Skip the rest.
  • policy is how approval is given: pin, otp_preferred or otp_only. With several types it is the strictest one.
    • pin: a manager PIN.
    • otp_preferred: a one-time code is preferred, a PIN is also accepted.
    • otp_only: a one-time code is needed. A PIN is accepted only after the code could not be sent (see below).
  • cancellation_types lists the asked types that need an approval.
  • approvers lists who can approve: approver_id, name, role_caption and can_receive_otp. When can_receive_otp is false, otp_unavailable_reason is no_phone or phone_unverified.

The approver's phone number is never returned by any approval call.

PIN Flow​

  1. Send POST /approvals/pin with the manager's pin (4 to 8 digits), the order_id of the paid order, the cancellation_types (at least one) and a gate_reason. Send approver_id to check one approver; leave it out to accept any approver of the outlet whose PIN matches.
  2. The answer has an approval_token, approver_id, approver_name, the order_id, expires_at, method and the cancellation_types it covers.
  3. Send the token as approval_token on the return, refund or exchange.

method in the answer is pin, otp or pin_fallback.

One-Time Code Flow​

  1. Send POST /approvals/otp with approver_id (one with can_receive_otp), order_id, cancellation_types and gate_reason. The answer has a request_id, expires_at, resend_after, sends_used and sends_max.
  2. The approver reads the 6 digit code. It works for 5 minutes.
  3. Send POST /approvals/otp/verify with the request_id and the code. The answer is the same as the PIN flow, with method otp.

Resend. Send the same body to POST /approvals/otp again to send a new code. At most 3 codes can be sent for the same order, user and types. Wait until resend_after: before that the call answers 409 OTP_RESEND_COOLDOWN and data.resend_after tells the time. This API never answers 429.

When no code can be sent. 409 OTP_UNAVAILABLE means no code can be sent now. data.reason tells why (for example no_reachable_approver, quota_exhausted, provider_error, cashier_cap_reached or resend_exhausted). The answer also has data.fallback_authorized (true) and data.fallback_expires_at: until that time you may use the PIN flow, and the token has method pin_fallback.

Token Rules​

  • It is valid for 5 minutes (expires_at).
  • It belongs to one order (order_id) and one user (the X-User-ID that asked for it).
  • It covers only the cancellation_types listed in the answer.
  • It works once. Ask for a new one for the next operation.

Lockout​

After 3 wrong PINs or codes for the same order and gate_reason at the outlet (counted for all users together), the check is locked for 15 minutes. The answer is 409 PIN_LOCKED with data.unlock_at. A wrong PIN answers 403 PIN_INVALID and a wrong code 403 OTP_INVALID; both have data.attempts_remaining.

warning

Never store PINs. Do not keep a manager's PIN in your system, your logs or your database. Ask for it, send it once, and drop it. Keep only the approval_token, and only until it is used.

Error Codes​

HTTPCodeWhen
400VALIDATION_FAILEDA field is missing or wrong, or types is missing or has an unknown value
403PIN_INVALIDThe PIN is wrong. data.attempts_remaining tells how many tries are left
403OTP_REQUIREDThe outlet needs a one-time code and no PIN fallback is open. Request a code first
403OTP_INVALIDThe code is wrong. data.attempts_remaining
403OTP_EXPIREDThe code expired, or the request_id is unknown or belongs to another user
403OTP_NOT_ENABLEDThe outlet does not use approval by one-time code
403PLAN_FEATURE_REQUIREDThe merchant's plan has no approval by one-time code
403APPROVER_NOT_ELIGIBLEThe approver is not on the outlet's approval line, or cannot receive a code while another can
404NOT_FOUNDThe order_id is unknown or is an order of another outlet
409SHIFT_NOT_OPENThe acting user has no open shift at the outlet (PIN and one-time code calls)
409PIN_LOCKEDToo many wrong tries. data.unlock_at tells when to try again
409OTP_RESEND_COOLDOWNA code was sent a moment ago. data.resend_after
409OTP_UNAVAILABLENo code can be sent now. A PIN fallback is open (see above)

These errors from the return, refund and exchange calls are about the token: 403 APPROVAL_REQUIRED (no token), 403 APPROVER_NOT_ELIGIBLE (the approver is not allowed) and 403 APPROVAL_TOKEN_INVALID (unknown, used, expired, or issued for another order, user or type; data.reason tells which). See Errors.