Zum Inhalt springen

Referenz

Referenz der POS-API

Die POS Posting API ist eine eigene, bestehende Schnittstelle für Kassensysteme: Sie bucht Restaurant-, Bar- oder Shopposten auf das Konto eines eingecheckten Aufenthalts. Sie verwendet eigene POS-Schlüssel aus den POS-Einstellungen in STRYK, keine Partner-API-Schlüssel.

STRYK POS Posting API Version 1.3.0

Vor der Anbindung

  • Diese Referenz beschreibt die direkte API. Sie ist kein zertifizierter Adapter für einen bestimmten Kassenhersteller.
  • Es gibt keine öffentliche Sandbox. Stimme einen Testablauf mit dem Hotel ab.
  • Die Einrichtung in STRYK Schritt für Schritt beschreibt die POS-Dokumentation.
Basis-URL
https://app.staystryk.com/api/v1/pos/public

Server-to-server interface for posting till items to physically checked-in hotel stays. STRYK issues a hotel-bound Bearer key once at creation; the stored hash cannot be revealed later. This documents the existing direct API, not a certified adapter for any named POS vendor. No public sandbox or automatic vendor onboarding is implied. Unknown optional response fields must be tolerated. The hotel needs the add-on STRYK POS; without it every call answers 403 with code module_disabled (no posting is written).

Authentication and provider direction

STRYK implements an inbound REST API with Bearer authentication. Mews similarly offers PMS APIs that a POS calls. Lightspeed K-Series specifies an OAuth-authorized PMS registration and its own callback protocol; that requires a provider-specific adapter, not merely pasting a STRYK key. No named vendor adapter is claimed here. Agree on integration ownership, outlet mapping, tax mapping and acceptance tests with the vendor before configuring a live till.

Supported scope

This interface performs room-account lookup, positive item posting, state recovery and cancellation. It is not a payment-terminal API, cash register, fiscal receipt service, product catalogue sync, stock system or full restaurant sales import. Cash/card payments settled at the till must not also be posted to the room. For split tenders send only the unpaid room portion, with correctly allocated tax and a unique reference per item; reconcile rounding explicitly. No negative-price, zero-price, discount, tip or refund endpoint exists. Apply item discounts before posting positive gross prices; financial corrections use the controlled cancellation or invoice workflow.

Hotel setup and account selection

Create the sales outlet with an active central tax, grant POS management only to authorized staff and issue one appropriately scoped key per connection. /ping only confirms key authentication; verify a controlled room posting before go-live. Use the live /accounts result or /room-lookup, show guest and room for confirmation, and send bookingId plus room. Do not persist the account list as an indefinite guest directory. No-Post, available credit, account closure, actual check-in/out and room segments are validated again when writing. Departure-day postings are allowed while the guest remains checked in; post-checkout imports are rejected.

Money, taxes and time

Use JSON numbers in hotel currency, positive gross unit prices, decimal arithmetic, quantity rounded HALF_UP to 3 decimals and money to 2. Maximum quantity 9999, unit price 99999.99, gross item total 99999999.99. Tax must be an active configured rate on the service date; omission resolves outlet/central defaults. Hotel timezone determines service dates. Freeze chargedAt and the complete request before first transmission. Never recalculate timestamps, prices, tax or references on retry.

Idempotency, offline recovery and key rotation

Persist outgoing requests locally on the POS server before sending. An externalRef belongs to hotel + API key, not the whole hotel. Exact POST replay returns 201, including an already transferred original item; cancelled references and changed payloads return 409. On timeout or 5xx first query the original reference. Only a confirmed 404 permits resending the same request with the same key. Check every line after an uncertain batch. If a member of staff manually posted the receipt during an outage, reconcile it before replay; posRef can assist but does not deduplicate. A new key creates a different idempotency scope and cannot look up/cancel the old key’s charges. Drain and reconcile outstanding work before revoking an old key. If it is lost or compromised, revoke it and resolve uncertain transactions in STRYK before submitting any replacements.

Error handling

400: fix invalid fields; 401: authentication could not be validated; 403: scope not allowed; 404: account/item absent; 409: business conflict (inspect code, do not blindly retry); 429: rate limit, wait at least 60 seconds; 5xx/network error: bounded backoff, state reconciliation and visible operator escalation. error contains human-readable text; code and requestId are optional. Never branch on German text or invent a new reference to bypass a failure. Any unlisted 5xx is also a service failure, never success.

Invoice handoff and audit

POST creates an open charge; it does not record payment. Checkout invoice generation transfers open charges into invoice positions. The API then returns status=transferred. Those items cannot be cancelled by the POS API; correct the invoice through STRYK Finance. Cancellation leaves an auditable cancelled charge. State lookup and cancellation cannot access another key’s items, even in the same hotel. General POS exports are available through the module statistics in STRYK.

Webhook delivery and verification

Configure an HTTPS target and a separate secret in POS Setup. Outbound POSTs use JSON and User-Agent STRYK-POS-Webhook/1.0. X-STRYK-Event is charge.posted or charge.cancelled; a manual connection test uses ping. X-STRYK-Webhook-Id is the subscription UUID, not an event or delivery ID. X-STRYK-Signature is sha256=<hex HMAC of exact UTF-8 request bytes> only when a secret is configured. Reject unsigned requests when expecting signed delivery. Persistently deduplicate event + data.chargeId (and hotelId where shared). Timestamp is generated per attempt, not a stable deduplication key. Deliveries may repeat or arrive out of order; do not let an old posted event overwrite cancellation. Respond 2xx only after durable acceptance, within 10 seconds; redirects are not followed. Failed deliveries enter the durable retry queue with delays of 30 seconds, 5 minutes, 30 minutes, then 2 hours, up to the stored attempt limit. Exhausted delivery state is visible in STRYK and needs operator reconciliation. There is no invoice-transfer or check-in/out webhook in this contract; re-read account/charge state as needed.

Acceptance checklist

Use an explicitly approved test hotel and real in-house test stay. Check ping, guest/room identity, multi-room booking selection, scoped outlet rejection, configured tax and currency, exact retry without a duplicate, changed-payload 409, lost response recovery, batch all-or-none, No-Post and credit-limit rejection, cancellation replay, checkout invoice totals and transferred cancellation rejection. Verify a signed webhook, invalid signature rejection and duplicate/out-of-order delivery. Confirm error visibility, key rotation and staff reconciliation before release. Do not execute these tests against unrelated guest stays.

Endpunkte

GET/pingCheck the connection

Scopes: Jeder gültige SchlüsseloperationId pingPosConnection

Antworten

  • 200Connection acceptedapplication/json
    • statusstringPflicht
    {
      "status": "ok"
    }
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl 'https://app.staystryk.com/api/v1/pos/public/ping' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY"
Beispiel, 200
{
  "status": "ok"
}

GET/accountsList currently checked-in room accounts

Scopes: Jeder gültige SchlüsseloperationId listChargeableAccounts

Antworten

  • 200Current in-house accounts, including No-Post and limit stateapplication/json
    • bookingIdstring (uuid)Pflicht
    • bookingNumberstringPflicht
    • guestNamestringPflicht
    • roomNumberstringPflicht
    • allowPostingbooleanPflicht

      Hotel No-Post policy. true alone does not imply a charge is permitted.

    • allowChargebooleanPflicht

      Combined eligibility, taking policy, available credit and closed invoice account into account.

    • accountClosedbooleanPflicht
    • postingBlockReasonstring | null

      Werte: "no_post", "credit_limit_reached", "account_closed", null

    • openChargesCountintegerPflicht
    • openChargesTotalnumberPflicht
    • stayChargesTotalnumberPflicht

      Non-cancelled stay charges, including transferred items. Credit policy uses this cumulative total.

    • creditLimitnumber | null
    • remainingCreditnumber | null
    • currencystringPflicht
    [
      {
        "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "bookingNumber": "string",
        "guestName": "string",
        "roomNumber": "string",
        "allowPosting": true,
        "allowCharge": true,
        "accountClosed": true,
        "postingBlockReason": "no_post",
        "openChargesCount": 0,
        "openChargesTotal": 1.5,
        "stayChargesTotal": 1.5,
        "creditLimit": 1.5,
        "remainingCredit": 1.5,
        "currency": "string"
      }
    ]
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl 'https://app.staystryk.com/api/v1/pos/public/accounts' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY"
Beispiel, 200
[
  {
    "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "bookingNumber": "string",
    "guestName": "string",
    "roomNumber": "string",
    "allowPosting": true,
    "allowCharge": true,
    "accountClosed": true,
    "postingBlockReason": "no_post",
    "openChargesCount": 0,
    "openChargesTotal": 1.5,
    "stayChargesTotal": 1.5,
    "creditLimit": 1.5,
    "remainingCredit": 1.5,
    "currency": "string"
  }
]

GET/room-lookupResolve a checked-in stay by room number

404 when no eligible current occupant exists. 409 when the room lookup is ambiguous. Never guess a guest from a room label or silently select the first match.

Scopes: Jeder gültige SchlüsseloperationId lookupRoomAccount

Parameter, query

NameOrtTypBeschreibung
roomPflichtquerystring-

Antworten

  • 200Unique current room accountapplication/json
    • bookingIdstring (uuid)Pflicht
    • bookingNumberstringPflicht
    • guestNamestringPflicht
    • roomNumberstringPflicht
    • allowPostingbooleanPflicht

      Hotel No-Post policy. true alone does not imply a charge is permitted.

    • allowChargebooleanPflicht

      Combined eligibility, taking policy, available credit and closed invoice account into account.

    • accountClosedbooleanPflicht
    • postingBlockReasonstring | null

      Werte: "no_post", "credit_limit_reached", "account_closed", null

    • openChargesCountintegerPflicht
    • openChargesTotalnumberPflicht
    • stayChargesTotalnumberPflicht

      Non-cancelled stay charges, including transferred items. Credit policy uses this cumulative total.

    • creditLimitnumber | null
    • remainingCreditnumber | null
    • currencystringPflicht
    {
      "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "bookingNumber": "string",
      "guestName": "string",
      "roomNumber": "string",
      "allowPosting": true,
      "allowCharge": true,
      "accountClosed": true,
      "postingBlockReason": "no_post",
      "openChargesCount": 0,
      "openChargesTotal": 1.5,
      "stayChargesTotal": 1.5,
      "creditLimit": 1.5,
      "remainingCredit": 1.5,
      "currency": "string"
    }
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 404Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 409Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl 'https://app.staystryk.com/api/v1/pos/public/room-lookup?room=room' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY"
Beispiel, 200
{
  "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "bookingNumber": "string",
  "guestName": "string",
  "roomNumber": "string",
  "allowPosting": true,
  "allowCharge": true,
  "accountClosed": true,
  "postingBlockReason": "no_post",
  "openChargesCount": 0,
  "openChargesTotal": 1.5,
  "stayChargesTotal": 1.5,
  "creditLimit": 1.5,
  "remainingCredit": 1.5,
  "currency": "string"
}

POST/chargesPost one item to an in-house account

externalRef is the immutable idempotency key of this POS connection. An exact retry returns the original charge with idempotentReplay=true. Reusing the reference with changed content or after cancellation returns 409.

Scopes: Jeder gültige SchlüsseloperationId postCharge

Request-Body application/json, Pflicht

  • bookingIdstring (uuid)

    Prefer this durable identity together with room; several room segments in one booking require an unambiguous room.

  • roomstring

    Actual room label, including letters; do not convert to a number. Must match bookingId when both are provided.

  • outletIdstring (uuid)

    Optional for an outlet-scoped key (scope is applied automatically). Any supplied value must match the key scope; mismatch is 403. An unrestricted key may choose an outlet.

  • descriptionstringPflicht
  • quantitynumber

    Defaults to 1; HALF_UP to 3 decimal places before validation.

  • unitstring
  • unitPricenumberPflicht

    Gross price per unit, not net. HALF_UP to 2 decimal places before validation. Positive only. Total gross (quantity × unitPrice rounded HALF_UP to 2 places) must be > 0 and <= 99999999.99.

  • taxRatenumber

    Configured active tax on the service date, rounded to 2 decimals. If omitted, use the outlet default, then the central service tax. An unconfigured rate is rejected.

  • currencystring

    Optional assertion; must equal the hotel's billing currency.

  • externalRefstringPflicht

    Stable, trimmed, case-sensitive receipt/item reference owned by the API key. Use URL-safe values (e.g. receipt-123-item-1) so GET/DELETE paths work through proxies. Never reuse for another item or replay under another key.

  • chargedAtstring (date-time)

    Optional service timestamp; defaults to now. Prefer ISO-8601 with offset. Legacy local timestamps use the hotel timezone. A time more than 5 minutes ahead is rejected. Service date must match a room segment, and the guest must still be physically in-house when posting. Keep the original timestamp unchanged on retries.

  • notesstring
  • posRefstring

    Optional receipt reference for staff reconciliation. It does not replace externalRef and does not provide idempotency.

Antworten

  • 201Created or exact idempotent replayapplication/json
    • chargeIdstring (uuid)Pflicht
    • externalRefstringPflicht
    • bookingIdstring (uuid)Pflicht
    • roomNumberstringPflicht
    • guestNamestringPflicht
    • outletIdstring (uuid)
    • outletNamestring
    • descriptionstringPflicht
    • quantitynumberPflicht
    • unitstring
    • unitPricenumberPflicht
    • taxRatenumberPflicht
    • grossAmountnumberPflicht
    • currencystringPflicht
    • statusstringPflicht

      Werte: "open", "cancelled", "transferred"

    • chargedAtstring (date-time)Pflicht
    • cancelledAtstring (date-time)
    • posRefstring
    • idempotentReplayboolean
    • duplicateWarningobject

      Advisory only: a potentially matching staff-entered item was found. The new charge has ALREADY been posted; reconcile in STRYK, do not resend.

      Felder anzeigen (5)
      • chargeIdstring (uuid)
      • descriptionstring
      • grossAmountnumber
      • chargedAtstring
      • posRefstring
    {
      "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "externalRef": "string",
      "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "roomNumber": "string",
      "guestName": "string",
      "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "outletName": "string",
      "description": "string",
      "quantity": 1.5,
      "unit": "string",
      "unitPrice": 1.5,
      "taxRate": 1.5,
      "grossAmount": 1.5,
      "currency": "string",
      "status": "open",
      "chargedAt": "2026-11-04T08:15:00.000Z",
      "cancelledAt": "2026-11-04T08:15:00.000Z",
      "posRef": "string",
      "idempotentReplay": false,
      "duplicateWarning": {
        "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "description": "string",
        "grossAmount": 1.5,
        "chargedAt": "string",
        "posRef": "string"
      }
    }
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 403Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 404Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 409Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl -X POST 'https://app.staystryk.com/api/v1/pos/public/charges' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY"
Beispiel, 201
{
  "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "externalRef": "string",
  "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "roomNumber": "string",
  "guestName": "string",
  "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "outletName": "string",
  "description": "string",
  "quantity": 1.5,
  "unit": "string",
  "unitPrice": 1.5,
  "taxRate": 1.5,
  "grossAmount": 1.5,
  "currency": "string",
  "status": "open",
  "chargedAt": "2026-11-04T08:15:00.000Z",
  "cancelledAt": "2026-11-04T08:15:00.000Z",
  "posRef": "string",
  "idempotentReplay": false,
  "duplicateWarning": {
    "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "description": "string",
    "grossAmount": 1.5,
    "chargedAt": "string",
    "posRef": "string"
  }
}

POST/charges/batchPost up to 50 items atomically

1-50 positions, each with its own externalRef; output order matches input. All newly created items commit together or none do. Existing exact replays may appear alongside new items. On uncertain outcome query each original reference before resending the unchanged batch. A conflicting or cancelled reference rejects the batch.

Scopes: Jeder gültige SchlüsseloperationId postChargeBatch

Request-Body application/json, Pflicht

  • bookingIdstring (uuid)

    Prefer this durable identity together with room; several room segments in one booking require an unambiguous room.

  • roomstring

    Actual room label, including letters; do not convert to a number. Must match bookingId when both are provided.

  • outletIdstring (uuid)

    Optional for an outlet-scoped key (scope is applied automatically). Any supplied value must match the key scope; mismatch is 403. An unrestricted key may choose an outlet.

  • descriptionstringPflicht
  • quantitynumber

    Defaults to 1; HALF_UP to 3 decimal places before validation.

  • unitstring
  • unitPricenumberPflicht

    Gross price per unit, not net. HALF_UP to 2 decimal places before validation. Positive only. Total gross (quantity × unitPrice rounded HALF_UP to 2 places) must be > 0 and <= 99999999.99.

  • taxRatenumber

    Configured active tax on the service date, rounded to 2 decimals. If omitted, use the outlet default, then the central service tax. An unconfigured rate is rejected.

  • currencystring

    Optional assertion; must equal the hotel's billing currency.

  • externalRefstringPflicht

    Stable, trimmed, case-sensitive receipt/item reference owned by the API key. Use URL-safe values (e.g. receipt-123-item-1) so GET/DELETE paths work through proxies. Never reuse for another item or replay under another key.

  • chargedAtstring (date-time)

    Optional service timestamp; defaults to now. Prefer ISO-8601 with offset. Legacy local timestamps use the hotel timezone. A time more than 5 minutes ahead is rejected. Service date must match a room segment, and the guest must still be physically in-house when posting. Keep the original timestamp unchanged on retries.

  • notesstring
  • posRefstring

    Optional receipt reference for staff reconciliation. It does not replace externalRef and does not provide idempotency.

Antworten

  • 201Charges in request orderapplication/json
    • chargeIdstring (uuid)Pflicht
    • externalRefstringPflicht
    • bookingIdstring (uuid)Pflicht
    • roomNumberstringPflicht
    • guestNamestringPflicht
    • outletIdstring (uuid)
    • outletNamestring
    • descriptionstringPflicht
    • quantitynumberPflicht
    • unitstring
    • unitPricenumberPflicht
    • taxRatenumberPflicht
    • grossAmountnumberPflicht
    • currencystringPflicht
    • statusstringPflicht

      Werte: "open", "cancelled", "transferred"

    • chargedAtstring (date-time)Pflicht
    • cancelledAtstring (date-time)
    • posRefstring
    • idempotentReplayboolean
    • duplicateWarningobject

      Advisory only: a potentially matching staff-entered item was found. The new charge has ALREADY been posted; reconcile in STRYK, do not resend.

      Felder anzeigen (5)
      • chargeIdstring (uuid)
      • descriptionstring
      • grossAmountnumber
      • chargedAtstring
      • posRefstring
    [
      {
        "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "externalRef": "string",
        "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "roomNumber": "string",
        "guestName": "string",
        "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "outletName": "string",
        "description": "string",
        "quantity": 1.5,
        "unit": "string",
        "unitPrice": 1.5,
        "taxRate": 1.5,
        "grossAmount": 1.5,
        "currency": "string",
        "status": "open",
        "chargedAt": "2026-11-04T08:15:00.000Z",
        "cancelledAt": "2026-11-04T08:15:00.000Z",
        "posRef": "string",
        "idempotentReplay": false,
        "duplicateWarning": {
          "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
          "description": "string",
          "grossAmount": 1.5,
          "chargedAt": "string",
          "posRef": "string"
        }
      }
    ]
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 403Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 404Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 409Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl -X POST 'https://app.staystryk.com/api/v1/pos/public/charges/batch' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '[]'
Beispiel, 201
[
  {
    "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "externalRef": "string",
    "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "roomNumber": "string",
    "guestName": "string",
    "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "outletName": "string",
    "description": "string",
    "quantity": 1.5,
    "unit": "string",
    "unitPrice": 1.5,
    "taxRate": 1.5,
    "grossAmount": 1.5,
    "currency": "string",
    "status": "open",
    "chargedAt": "2026-11-04T08:15:00.000Z",
    "cancelledAt": "2026-11-04T08:15:00.000Z",
    "posRef": "string",
    "idempotentReplay": false,
    "duplicateWarning": {
      "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "description": "string",
      "grossAmount": 1.5,
      "chargedAt": "string",
      "posRef": "string"
    }
  }
]

GET/charges/{externalRef}Recover the durable state of one POS transaction

Use this read before retrying after a timeout or lost response. The externalRef is resolved only inside the authenticated API-key connection and returns open, cancelled, and transferred charges.

Scopes: Jeder gültige SchlüsseloperationId getChargeByExternalReference

Parameter, path

NameOrtTypBeschreibung
externalRefPflichtpathstring-

Antworten

  • 200Current durable transaction stateapplication/json
    • chargeIdstring (uuid)Pflicht
    • externalRefstringPflicht
    • bookingIdstring (uuid)Pflicht
    • roomNumberstringPflicht
    • guestNamestringPflicht
    • outletIdstring (uuid)
    • outletNamestring
    • descriptionstringPflicht
    • quantitynumberPflicht
    • unitstring
    • unitPricenumberPflicht
    • taxRatenumberPflicht
    • grossAmountnumberPflicht
    • currencystringPflicht
    • statusstringPflicht

      Werte: "open", "cancelled", "transferred"

    • chargedAtstring (date-time)Pflicht
    • cancelledAtstring (date-time)
    • posRefstring
    • idempotentReplayboolean
    • duplicateWarningobject

      Advisory only: a potentially matching staff-entered item was found. The new charge has ALREADY been posted; reconcile in STRYK, do not resend.

      Felder anzeigen (5)
      • chargeIdstring (uuid)
      • descriptionstring
      • grossAmountnumber
      • chargedAtstring
      • posRefstring
    {
      "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "externalRef": "string",
      "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "roomNumber": "string",
      "guestName": "string",
      "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "outletName": "string",
      "description": "string",
      "quantity": 1.5,
      "unit": "string",
      "unitPrice": 1.5,
      "taxRate": 1.5,
      "grossAmount": 1.5,
      "currency": "string",
      "status": "open",
      "chargedAt": "2026-11-04T08:15:00.000Z",
      "cancelledAt": "2026-11-04T08:15:00.000Z",
      "posRef": "string",
      "idempotentReplay": false,
      "duplicateWarning": {
        "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "description": "string",
        "grossAmount": 1.5,
        "chargedAt": "string",
        "posRef": "string"
      }
    }
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 404Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl 'https://app.staystryk.com/api/v1/pos/public/charges/externalRef' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY"
Beispiel, 200
{
  "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "externalRef": "string",
  "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "roomNumber": "string",
  "guestName": "string",
  "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "outletName": "string",
  "description": "string",
  "quantity": 1.5,
  "unit": "string",
  "unitPrice": 1.5,
  "taxRate": 1.5,
  "grossAmount": 1.5,
  "currency": "string",
  "status": "open",
  "chargedAt": "2026-11-04T08:15:00.000Z",
  "cancelledAt": "2026-11-04T08:15:00.000Z",
  "posRef": "string",
  "idempotentReplay": false,
  "duplicateWarning": {
    "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "description": "string",
    "grossAmount": 1.5,
    "chargedAt": "string",
    "posRef": "string"
  }
}

DELETE/charges/{externalRef}Void an open charge owned by this POS connection

Only this key’s open items can be cancelled. Repeating a successful cancellation returns the existing cancelled item. Transferred/invoiced items return 409 pos_charge_already_invoiced and need the Finance correction workflow. Cancellation is not deletion or a refund.

Scopes: Jeder gültige SchlüsseloperationId cancelCharge

Parameter, path

NameOrtTypBeschreibung
externalRefPflichtpathstring-

Request-Body application/json, optional

  • reasonstring

Antworten

  • 200Cancelled charge, or an idempotent repeat of the cancellationapplication/json
    • chargeIdstring (uuid)Pflicht
    • externalRefstringPflicht
    • bookingIdstring (uuid)Pflicht
    • roomNumberstringPflicht
    • guestNamestringPflicht
    • outletIdstring (uuid)
    • outletNamestring
    • descriptionstringPflicht
    • quantitynumberPflicht
    • unitstring
    • unitPricenumberPflicht
    • taxRatenumberPflicht
    • grossAmountnumberPflicht
    • currencystringPflicht
    • statusstringPflicht

      Werte: "open", "cancelled", "transferred"

    • chargedAtstring (date-time)Pflicht
    • cancelledAtstring (date-time)
    • posRefstring
    • idempotentReplayboolean
    • duplicateWarningobject

      Advisory only: a potentially matching staff-entered item was found. The new charge has ALREADY been posted; reconcile in STRYK, do not resend.

      Felder anzeigen (5)
      • chargeIdstring (uuid)
      • descriptionstring
      • grossAmountnumber
      • chargedAtstring
      • posRefstring
    {
      "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "externalRef": "string",
      "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "roomNumber": "string",
      "guestName": "string",
      "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
      "outletName": "string",
      "description": "string",
      "quantity": 1.5,
      "unit": "string",
      "unitPrice": 1.5,
      "taxRate": 1.5,
      "grossAmount": 1.5,
      "currency": "string",
      "status": "open",
      "chargedAt": "2026-11-04T08:15:00.000Z",
      "cancelledAt": "2026-11-04T08:15:00.000Z",
      "posRef": "string",
      "idempotentReplay": false,
      "duplicateWarning": {
        "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
        "description": "string",
        "grossAmount": 1.5,
        "chargedAt": "string",
        "posRef": "string"
      }
    }
  • 400Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 401Key could not be validated (missing, invalid, revoked, or verification unavailable). Check configuration and service status; do not automatically rotate credentials or replay under a new key.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 404Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 409Request rejectedapplication/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 429100 requests per 60-second window per key, shared across application instances. No Retry-After header is currently returned. Wait at least 60 seconds, then retry with backoff and jitter. Reconcile uncertain writes before retrying.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
  • 500Unexpected service error. A failed or lost response is not proof that a write was rolled back. Reconcile GET /charges/{externalRef} before retrying with the original key and request. Back off for transient 5xx and network failures. Escalate persistent errors with requestId; never change reference to bypass an error.application/json
    • errorstringPflicht
    • codestring

      Optional machine-readable code. Do not parse localized error text. This list is extensible.

    • requestIdstring

      Optional diagnostic request identifier; retain for support without credentials or guest data.

    {
      "error": "string",
      "code": "pos_currency_mismatch",
      "requestId": "string"
    }
curl -X DELETE 'https://app.staystryk.com/api/v1/pos/public/charges/externalRef' \
  -H "Authorization: Bearer $STRYK_POS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
  "reason": "string"
}'
Beispiel, 200
{
  "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "externalRef": "string",
  "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "roomNumber": "string",
  "guestName": "string",
  "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
  "outletName": "string",
  "description": "string",
  "quantity": 1.5,
  "unit": "string",
  "unitPrice": 1.5,
  "taxRate": 1.5,
  "grossAmount": 1.5,
  "currency": "string",
  "status": "open",
  "chargedAt": "2026-11-04T08:15:00.000Z",
  "cancelledAt": "2026-11-04T08:15:00.000Z",
  "posRef": "string",
  "idempotentReplay": false,
  "duplicateWarning": {
    "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "description": "string",
    "grossAmount": 1.5,
    "chargedAt": "string",
    "posRef": "string"
  }
}

Webhook-Ereignisse

Signaturprüfung und Wiederholungen

POSTchargeEventSTRYK sends a charge event to the configured HTTPS receiver

Zustell-Header

NameOrtTypBeschreibung
X-STRYK-EventPflichtheaderstring-
X-STRYK-Webhook-IdPflichtheaderstring (uuid)

Subscription ID, not unique delivery ID.

X-STRYK-Signatureheaderstring

Present only for subscriptions with a signing secret. Configure one and verify the original raw bytes.

Payload application/json, Pflicht

  • eventstringPflicht

    Werte: "charge.posted", "charge.cancelled", "ping"

  • hotelIdstringPflicht
  • timestampstring (date-time)Pflicht

    Attempt timestamp, may differ on retry.

  • dataobjectPflicht

    Charge events contain chargeId, externalRef if present, bookingId, roomNumber, guestName, description, grossAmount, currency, outletId/outletName if present. A ping carries test data instead.

    Felder anzeigen (11)
    • chargeIdstring (uuid)
    • externalRefstring
    • bookingIdstring (uuid)
    • roomNumberstring
    • guestNamestring
    • descriptionstring
    • grossAmountnumber
    • currencystring
    • outletIdstring (uuid)
    • outletNamestring
    • testboolean

Antworten

  • 200Durably accepted; any 2xx is accepted
  • defaultDelivery failed; queued retry subject to attempt limit
Payload
{
  "event": "charge.posted",
  "hotelId": "string",
  "timestamp": "2026-11-04T08:15:00.000Z",
  "data": {
    "chargeId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "externalRef": "string",
    "bookingId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "roomNumber": "string",
    "guestName": "string",
    "description": "string",
    "grossAmount": 1.5,
    "currency": "string",
    "outletId": "3f1c2b9a-6d4e-4b8a-9c7e-1a2b3c4d5e6f",
    "outletName": "string",
    "test": true
  }
}