Skip to content

Configuration Endpoints

Hyvä POS is in closed beta

Hyvä POS is currently in a closed beta (pilot phase) with a small group of merchants. It is not yet generally available: the App Store release follows the pilot, and features and configuration may still change - possibly in backwards-incompatible ways - before the general release. Want to take part? Sign up at hyva.io/pos.

These endpoints carry admin settings to the register. The device reads the global config and the unified per-terminal payload; it never writes configuration through them (the write path is PUT /V1/pos/locations/:locationId/config, documented in Locations and Terminals).

Method Route ACL Purpose
GET /V1/pos/config Hyva_Pos::locations Global POS configuration, defaults, enforcement flags
GET /V1/pos/terminals/:terminalId/config Hyva_Pos::locations Unified per-terminal bootstrap payload
GET /V1/pos/postcode-patterns Hyva_Pos::locations Per-country postcode validation patterns
GET /V1/pos/order-statuses Hyva_Pos::locations Registered order statuses for picker UIs

Global Config - GET /V1/pos/config

Returns everything under Stores > Configuration > Hyvä POS as one object, plus feature-availability flags derived from the installed modules and provider pools. Called by the iPad on every settings sync, including before a PRO module is detected - it is how the app discovers what the store supports.

The response body is a JSON-encoded string (the object serialized twice). Parse the body, then parse the resulting string. Abridged example after decoding:

{
  "module_version": "1.1.0",
  "enabled": true,
  "require_staff_login": true,
  "share_held_carts": true,
  "require_terminal_registration": true,
  "default_order_status": "",
  "default_payment_methods": "cash,card",
  "default_low_stock_threshold": 10,
  "default_receipt_header": "Thank you for shopping with us",
  "default_receipt_footer": "",
  "default_receipt_show_staff_name": true,
  "default_receipt_show_order_number": true,
  "default_layaway_deposit_min_percent": 25,
  "default_layaway_expiry_days": 30,
  "default_layaway_cancellation_fee_percent": 0,
  "default_pickup_queue_filter": "all",
  "card_payments": {
    "provider": "mollie",
    "mollie": {
      "enabled": true,
      "organisation_id": "org_12345",
      "api_key": "live_...",
      "test_api_key": "test_...",
      "test_mode": false
    }
  },
  "walk_in_customer": {
    "first_name": "POS",
    "last_name": "Customer",
    "email": "store@example.com",
    "phone": "+31 20 123 4567",
    "street": "Main Street 1",
    "city": "Amsterdam",
    "region_id": 0,
    "postcode": "1234AB",
    "country_id": "NL"
  },
  "telemetry": { "enabled": false, "force_enabled": false, "upload_hour": 3 },
  "tax": {
    "price_includes_tax": true,
    "apply_after_discount": true,
    "discount_tax": true,
    "display_type": 2,
    "cart_display_price": 2,
    "cart_display_subtotal": 2
  },
  "enforcement": { "receipt_header": "1", "payment_methods": "0", "tax_settings": "1" },
  "payments": {
    "pay_by_invoice_method": "checkmo",
    "pay_by_invoice_invoicing_mode": "open",
    "credit_limits_enabled": true,
    "providers": { "mollie": { "magento_method": "mollie_methods_pointofsale" } },
    "available_terminal_payment_methods": [
      { "code": "checkmo", "label": "Check / Money order" },
      { "code": "mollie_methods_pointofsale", "label": "Point of sale" }
    ],
    "builtin_refunds_enabled": true
  },
  "credits": {
    "store_credit_includes_tax": false,
    "reward_points_includes_tax": false,
    "gift_card_includes_tax": false
  },
  "license": { "connected": true },
  "has_credit_providers": true,
  "has_rma_providers": true,
  "has_wishlist": true,
  "has_customer_balance": false,
  "has_gift_card": false,
  "has_reward_points": false,
  "has_rma_module": false,
  "shipping_label_providers": [],
  "credit_providers": [
    { "key": "store_credit", "code": "pos_builtin", "enabled": true, "label": "Store Credit" }
  ],
  "rma_providers": [
    { "key": "rma", "code": "pos_builtin", "enabled": true, "label": "Built-in Returns" }
  ]
}

The default_* keys are website- or store-scope fallbacks; a location row without an explicit value inherits them. The card_payments.mollie block contains decrypted API keys for the device - scope integration tokens accordingly.

Unified Terminal Config - GET /V1/pos/terminals/:terminalId/config

The bootstrap payload the iPad pulls at activation, at launch, and whenever the heartbeat's config_hash changes. One call replaces separate fetches of config, location, staff, and roles. Also a JSON-encoded string; parse twice. Envelope keys:

Key Content
terminal The terminal row, with license fields injected: license_id, license_token, license_status, license_type, license_expires_at, fiskaly_tss_id, fiskaly_api_key
license The full linked license record, or null
config The same object as GET /V1/pos/config
location The terminal's location row, with the address already resolved (when address_use_storeview is on, store-view values are swapped in server-side)
resolved_config The effective flat config: terminal overrides layered over location values over global defaults. Read this instead of re-implementing precedence
staff Active staff assigned to the location (or with all_locations). The bcrypt passcode hash is stripped; passcode_updated_at is included
roles The roles referenced by those staff rows

Errors: 404 with Terminal with id "%1" does not exist. for an unknown terminal id. A deleted location yields "location": null rather than an error.

Enforcement Flags and How Locks Work

Each flag lives at hyva_pos_lock/enforcement/<field> (website scope, Stores > Configuration > Hyvä POS > Lock Settings) and is delivered in the enforcement block as string "1" (enforced - the device renders the setting read-only and shows it as managed) or "0" (the device may customize it per location). Server-side, PUT /V1/pos/locations/:locationId/config skips locked fields. Defaults are "0".

Flag Locks
receipt_header / receipt_footer Receipt header and footer text
receipt_show_staff_name / receipt_show_order_number Cashier-name and order-number visibility on receipts
receipt_qr Receipt-bottom QR text and URL
payment_methods The set of available payment methods
mollie_magento_method Which Magento payment method backs Mollie-routed card sales (per-location overrides ignored)
mollie_config Mollie terminal settings (keys, organisation id, test mode)
pay_by_invoice_method / pay_by_invoice_invoicing_mode Pay-by-invoice payment method and invoice behavior
store_details Store address, phone, and VAT number
tax_settings Tax calculation and display settings
low_stock_threshold The low-stock warning threshold
held_carts The "Share Held Carts" toggle
categories Which top-level categories appear on the register landing page
walk_in_customer Walk-in customer default name / email / phone / address
pickup_queue_filter The default pickup-queue filter

Postcode Patterns - GET /V1/pos/postcode-patterns

Relays Magento's etc/postcodes.xml so the device can validate addresses client-side without a parallel hardcoded list. Returns a JSON-encoded string keyed by ISO 3166-1 alpha-2 country code; each country maps to an array of {pattern, example} rows, and any matching row is a pass (the US, for example, has both 5-digit and ZIP+4 rows):

{
  "NL": [{ "pattern": "^[0-9]{4} ?[a-zA-Z]{2}$", "example": "1234AB" }],
  "US": [
    { "pattern": "^[0-9]{5}$", "example": "12345" },
    { "pattern": "^[0-9]{5}-[0-9]{4}$", "example": "12345-6789" }
  ]
}

Order Statuses - GET /V1/pos/order-statuses

Every registered row from sales_order_status, including custom merchant statuses. Feeds the location-config "post-pickup status" dropdown (pickup_completed_status_code) so merchants never depend on hard-coded module values.

[
  { "status": "processing", "label": "Processing" },
  { "status": "complete", "label": "Complete" },
  { "status": "picked_up", "label": "Picked Up In Store" }
]