RMO Developers

Card Authorizations

Authorize, capture, reverse, and increment card transactions. Token-only — you never send a raw PAN.

How tokens work. Every RMO card is referenced by a 17-character opaque panToken. The token comes from your terminal SDK (chip / swipe / tap) or your tokenization service — never from a user typing card digits. The PAN itself never traverses api.rmous.org, which keeps your integration out of PCI-DSS scope.

Lifecycle

A new authorization moves through one of these paths:

POST /v1/authorizations
  ↓
[Authorization Approved]  — hold on the card, funds reserved
  ↓  POST /capture
[Authorization Partial]   — some captured, more remaining
  ↓  POST /capture (remainder)
[Authorization Charged]   — terminal, fully captured
  ↓  POST /reverse
[Authorization Reversed]  — terminal, refunded

OR

POST /v1/authorizations
  ↓
[Authorization Declined]  — terminal, audit-only

Create

POST/v1/authorizations

Submit a new card authorization. The pipeline: resolve panToken → card status gate → expiration gate → limit-engine evaluation → idempotency replay check → INSERT Issuing.Authorizations → fire authorization.approved or .declined webhook.

Body

FieldTypeDescription
panToken requiredstring(17)Opaque card token from your terminal SDK or tokenization service.
amount requirednumberPositive number. USD by default.
currency optionalstringCore.Currencies.RecordId. Defaults to USD.
channel optionalstringIssuing.Channels.RecordId: POS, ECOMM, etc.
mcc optionalstring(4)4-digit merchant-category code.
merchant optionalstringMerchant.Accounts.RecordId.
merchantNameRaw optionalstringUp to 64 chars. What appears on the cardholder’s statement.
avsResult optionalenumY / N / A / Z / U
cvvResult optionalenumM / N / P / U / X
mode optionalenum01 card-present · 02 CNP · 03 recurring · 04 token · 05 MOTO
metadata optionalobjectJSON passthrough — opaque to RMO, returned as-is on read.

Example

curl https://api.rmous.org/v1/authorizations \
  -H "X-API-Key: pk_test_publicsandbox_2026" \
  -H "Authorization: Bearer sk_test_publicsandbox_2026_anyone_can_use_this" \
  -H "Idempotency-Key: order-7421" \
  -H "Content-Type: application/json" \
  -d '{
    "panToken": "TOKEN_FROM_TERMINAL",
    "amount":   42.50,
    "channel":  "POS",
    "mcc":      "5812",
    "merchantNameRaw": "RMO Coffee Shop",
    "mode":     "01"
  }'

Approved response (201)

{
  "authorizationId": "7421589",         // 7-digit human ID
  "recordId":        "A1b2C3d4E5f6G7h8I", // 17-char system ID
  "status":          "approved",
  "amount":          42.50,
  "approvalCode":    "A7B2C3",         // 6-digit
  "expires":         "2026-05-21T16:53:05Z" // hold expiry, 7d default
}

Declined response (200)

{
  "authorizationId": "7421590",
  "recordId":        "D1e2C3l4I5n6E7d8X",
  "status":          "declined",
  "amount":          42.50,
  "reasonCode":      "61",
  "reasonMessage":   "Daily spend cap exceeded",
  "details": { "limits": [ // limit-engine breach detail ] }
}

A declined response is still a successful HTTP request (200) — the network reached a decision. reasonCode follows ISO-8583 conventions; see Errors.

Capture

POST/v1/authorizations/{id}/capture

Convert an approved hold into a posted charge. Omitting amount captures the full remaining hold. Partial captures are allowed — the auth stays open at Authorization Partial until the remainder is captured or reversed.

Body

FieldTypeDescription
amount optionalnumberPartial capture amount. Must be ≤ remaining. Defaults to full remainder.
curl https://api.rmous.org/v1/authorizations/7421589/capture \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER" \
  -H "Idempotency-Key: capture-7421589-1" \
  -H "Content-Type: application/json" \
  -d '{"amount": 30.00}'

# Response (200):
{
  "authorizationId": "7421589",
  "status":          "partial",    // or "charged" when fully captured
  "amountCaptured":  30.00,
  "acknowledged":    "2026-05-14T17:01:33Z",
  "settled":         null            // only set when status="charged"
}

Fires authorization.captured webhook on success.

Reverse / refund

POST/v1/authorizations/{id}/reverse

One endpoint covers both void (before capture) and refund (after capture). The behavior is determined by the auth’s current state.

FieldTypeDescription
amount optionalnumberPartial reverse amount. Defaults to full remaining hold or full captured amount.
reason optionalstringIssuing.Reasons.Code. Defaults to RV02 (customer void).
{
  "authorizationId": "7421589",
  "status":          "reversed",     // or "partial-reversed"
  "amountReversed":  42.50,
  "reasonCode":      "RV02",
  "settled":         "2026-05-14T17:08:11Z"
}

Fires authorization.reversed webhook on success.

Incremental authorization

POST/v1/authorizations/{id}/increment

For hotels, gas pumps, ride-share, and other open-tab scenarios. The original auth stays open; a new Authorizations row is written with isIncremental: true and parentAuthorization pointing at the original. Limit-engine evaluates against the additional amount on the parent’s card.

FieldTypeDescription
amount requirednumberAdditional amount to hold.
metadata optionalobjectJSON passthrough.
{
  "authorizationId":     "7421593",
  "recordId":            "I1n2C3r4E5m6T7n8L",
  "parentAuthorization": "7421589",
  "status":              "approved",
  "amount":              15.00,
  "approvalCode":        "A8C4F1",
  "expires":             "2026-05-21T16:53:05Z"
}

Read

GET/v1/authorizations/{id}

Look up an authorization by either its 7-digit Id (the human ID returned as authorizationId) or its 17-character RecordId. Only the issuing tenant can see their own authorizations.

curl https://api.rmous.org/v1/authorizations/7421589 \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER"

Where to next

Payment codes → Listen for events → Error reference →