Developer dashboard

Device Management#

Manage POS devices and payment terminals associated with a merchant account. This covers the full device lifecycle — provisioning, configuration, templates, and pairing.


Overview#

The device system has three components:

Component Base Path Auth Purpose
Devices /api/v1/merchants/:merchantId/devices User JWT CRUD for device records
Parameters /api/v1/merchants/:merchantId/devices/:deviceId/parameters User JWT Per-device configuration
Templates /api/v1/merchants/:merchantId/device-templates User JWT Reusable parameter presets

All portal endpoints require an Authorization: Bearer <jwt> header. The tenant is taken from the token (it is forwarded to the merchant service as X-Tenant-ID).

The branches.manage permission (Locations & Devices) controls serial-number visibility: callers without it still see devices, but sunmiSN is returned in full on device reads, and Reveal Serial Number returns 403. Reads (GET) by merchant users are limited to their own merchant; tenant admins need merchants.view.

For mobile app / POS integration, see the Mobile Device Integration guide.


Devices#

List Devices#

GET/api/v1/merchants/:merchantId/devices

Query Parameters:

Parameter Type Default Description
status enum — Filter by status: PENDING, REGISTERED, ACTIVE, INACTIVE, SUSPENDED, ARCHIVED
limit number 50 Results per page
offset number 0 Pagination offset

Archived devices: Omitting status, or filtering by any status other than ARCHIVED, always excludes archived (soft-deleted) devices. Pass status=ARCHIVED explicitly to list archived devices — this is the only way to see them.

Example:

List Devicesbash
curl "https://uat.auxcore.net/api/v1/merchants/8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30/devices?status=ACTIVE&limit=20" \
  -H "Authorization: Bearer YOUR_JWT"

Response:

List Devicesjson
{
  "success": true,
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "tenantId": "your-tenant-id",
      "merchantId": "8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30",
      "branchId": null,
      "deviceLabel": "Front Counter POS",
      "deviceNumber": 1001,
      "tpn": "483920174651",
      "manufacturer": "ANDROID_PHONE",
      "deviceType": "TAP_ON_PHONE",
      "paymentMode": "AUXVAULT",
      "merchantGatewayId": "2b9e7d1c-4f3a-4e8b-a5d6-7c0f1e2b3a48",
      "gateway": "NMI",
      "paymentAdjustmentType": "NONE",
      "paymentAdjustmentValue": null,
      "paymentAdjustmentCardValue": null,
      "paymentAdjustmentAchValue": null,
      "autoSettleEnabled": false,
      "settleAt": null,
      "templateId": "550e8400-e29b-41d4-a716-446655440099",
      "mid": "123456789012",
      "terminalId": "TID001",
      "iposTpn": null,
      "iposTpnCode": null,
      "nearpayTid": null,
      "sunmiSN": null,
      "serialMasked": null,
      "hasSerial": false,
      "hasApiKey": true,
      "skipTestConnection": false,
      "status": "ACTIVE",
      "pairingCode": "482910",
      "appVersion": "2.1.0",
      "osVersion": "14.0",
      "osPlatform": "ANDROID",
      "registeredAt": "2026-03-15T09:00:00.000Z",
      "registeredByUserId": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "assignedUserId": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "isShared": false,
      "lastActiveAt": "2026-04-14T08:32:00.000Z",
      "txCount": 247,
      "txVolumeUsd": "14820.50",
      "todayVolume": 312.4,
      "todayTransactionCount": 6,
      "createdBy": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "updatedBy": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "createdAt": "2026-03-10T00:00:00.000Z",
      "updatedAt": "2026-04-14T08:32:00.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "total": 1,
    "limit": 20,
    "offset": 0
  }
}

Note: The encrypted gateway API key is never returned; hasApiKey tells you whether one is set. txCount / txVolumeUsd are lifetime totals; todayVolume / todayTransactionCount cover today and are null when the figure could not be loaded.


Create Device#

POST/api/v1/merchants/:merchantId/devices

Request Body:

Field Type Required Description
deviceLabel string Yes Human-readable name
manufacturer enum Yes ANDROID_PHONE | APPLE_PHONE | SUNMI (Dejavoo terminals are also accepted and must use IPOS)
deviceType enum Yes TAP_ON_PHONE | CARD_READER | POS_TERMINAL
paymentMode enum Yes AUXVAULT | IPOS | NEARPAY
merchantGatewayId uuid No Merchant gateway the device uses. Must belong to this merchant and be ACTIVE. The gateway code is derived from it.
branchId uuid No Location (child merchant) the device belongs to. Must belong to this merchant.
assignedUserId uuid No Team member the device belongs to. Omit for a shared device (isShared is derived).
templateId uuid No Applies template parameters at creation time
mid string No Merchant ID at gateway
terminalId string No Terminal ID at gateway
apiKey string No Gateway API key (encrypted at rest with AES-256-GCM)
iposTpn string No iPOSpays Terminal Processor Number (for IPOS). Must be unique across devices.
iposTpnCode string No iPOSpays TPN code
nearpayTid string No NearPay terminal ID (for NEARPAY)
sunmiSN string No Serial Number — for Sunmi hardware devices
skipTestConnection boolean No Device becomes ACTIVE on registration without a test-connection step
paymentAdjustmentType enum No NONE (default) | FLAT | PERCENTAGE
paymentAdjustmentValue, paymentAdjustmentCardValue, paymentAdjustmentAchValue decimal string No Adjustment amounts
autoSettleEnabled boolean No Default false
settleAt string No Auto-settle time

Example:

Create Devicebash
curl -X POST "https://uat.auxcore.net/api/v1/merchants/8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30/devices" \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "deviceLabel": "Drive-Thru Terminal",
    "manufacturer": "ANDROID_PHONE",
    "deviceType": "TAP_ON_PHONE",
    "paymentMode": "AUXVAULT",
    "merchantGatewayId": "2b9e7d1c-4f3a-4e8b-a5d6-7c0f1e2b3a48",
    "mid": "123456789012",
    "terminalId": "TID002",
    "templateId": "550e8400-e29b-41d4-a716-446655440099"
  }'

Response (201 Created):

Create Devicejson
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440002",
    "deviceNumber": 1002,
    "tpn": "739201847362",
    "pairingCode": "619274",
    "status": "PENDING",
    "createdAt": "2026-04-14T10:00:00.000Z",
    ...
  }
}

Auto-generated fields:

Field Rule
tpn 12-digit numeric, globally unique. Retry up to 10x on collision
pairingCode 6-digit numeric, unique per tenant. Used to pair the mobile app
deviceNumber Sequential per merchant starting at 1001; never reused

Errors: 400 Missing required fields; 400 VALIDATION_ERROR for a gateway that does not belong to the merchant or is not active, a branch that does not belong to the merchant, a duplicate iposTpn, or a Dejavoo device not using IPOS.

If templateId is provided: Parameters are automatically created from the template. The mobile app will receive the template-configured values on its first GET /device/parameters call.


Get Device#

GET/api/v1/merchants/:merchantId/devices/:deviceId

Returns a single device object, including archived (soft-deleted) devices — check status === "ARCHIVED" in the response if you need to distinguish them. Returns 404 only if the device does not exist at all.


Update Device#

PATCH/api/v1/merchants/:merchantId/devices/:deviceId

All create fields are optional here. Only supplied fields are updated.

Request Body:

Update Devicejson
{
  "deviceLabel": "Updated Label",
  "branchId": "3d1f8e2a-7c4b-4a9e-8f2d-1b6c9e0a5d47",
  "mid": "999999999999",
  "terminalId": "TID003",
  "apiKey": "new-plaintext-gateway-key",
  "templateId": "550e8400-e29b-41d4-a716-446655440099"
}
  • merchantGatewayId: null clears the gateway. Switching to a different gateway requires it to be ACTIVE.
  • branchId: null (or "") removes the location; changing it records a reassignment in the device and location activity.
  • A masked sunmiSN value sent back is ignored.

Note: tpn and pairingCode are immutable after creation and cannot be updated via this endpoint. Use Refresh Pairing Code to issue a new pairing code.

Response (200 OK): Updated device object.


Update Device Status#

PATCH/api/v1/merchants/:merchantId/devices/:deviceId/status

Request Body:

Update Device Statusjson
{
  "status": "ACTIVE"
}

Status Transition Rules:

PENDING, REGISTERED, ACTIVE, INACTIVE, and SUSPENDED are freely inter-transitionable — any of these five statuses can be set from any other via this endpoint (e.g. SUSPENDED → ACTIVE, SUSPENDED → PENDING, ACTIVE → PENDING are all allowed). Setting the status the device already has returns 422.

An unknown status returns 400 Invalid status value. ARCHIVED is not a valid target for this endpoint — requesting "status": "ARCHIVED" always returns 422 Unprocessable Entity. Use Archive Device instead. Likewise, an archived device cannot be reached by this endpoint at all (it's excluded from the underlying lookup, 404) — use Unarchive Device to restore it first.

Side effects when moving out of ACTIVE: All active device sessions are immediately revoked — for any target status, not only SUSPENDED. The mobile app receives 401 Unauthorized on its next request (or reusable: false, reason: "NOT_ACTIVE" from GET /api/v1/device/session) and must register again.

This is what releases a device: a device that is no longer ACTIVE can no longer be reused by the app that holds its token, and the merchant user is asked for TPN + Pairing Code again. Transitioning to ACTIVE leaves existing sessions untouched.


Delete Device#

DELETE/api/v1/merchants/:merchantId/devices/:deviceId

Soft-deletes the device — sets status to ARCHIVED and deletedAt to now. Functionally identical to Archive Device; kept for backward compatibility. New integrations should prefer POST .../archive.

Side effects: All active sessions are revoked with reason ARCHIVED.

Response:

Delete Devicejson
{
  "success": true,
  "message": "Device deleted"
}

Archive Device#

POST/api/v1/merchants/:merchantId/devices/:deviceId/archive

Soft-deletes the device: sets status to ARCHIVED and deletedAt to now. The device is immediately excluded from the default device list and from any status-filtered list other than status=ARCHIVED.

Side effects: All active sessions are revoked with reason ARCHIVED. The mobile app will receive 401 Unauthorized on its next request.

Request Body: empty

Response:

Archive Devicejson
{
  "success": true,
  "message": "Device archived"
}

Unarchive Device#

POST/api/v1/merchants/:merchantId/devices/:deviceId/unarchive

Restores a previously archived device: clears deletedAt and sets status to INACTIVE. The device reappears in the default device list. The admin must explicitly reactivate it afterward (e.g. via Update Device Status) — it is never restored directly to ACTIVE.

Request Body: empty

Response (200 OK): Updated device object (status: "INACTIVE").

Errors:

  • 404 Not Found — device does not exist.
  • 422 Unprocessable Entity — device is not currently archived ("Device is not archived").

Refresh Pairing Code#

POST/api/v1/merchants/:merchantId/devices/:deviceId/refresh-pairing-code

Generates a new pairing code and resets the device to PENDING status. Use this when:

  • A device needs to be re-paired to a different handset
  • The original pairing code was compromised

Request Body: empty

Response:

Refresh Pairing Codejson
{
  "success": true,
  "data": {
    "status": "PENDING",
    "pairingCode": "827461",
    "appVersion": null,
    "osVersion": null,
    "osPlatform": null,
    "registeredAt": null,
    ...
  }
}

Side effects:

  • Device status reset to PENDING
  • All active sessions revoked with reason PAIRING_REFRESHED
  • Hardware binding (appVersion, osVersion, osPlatform, registeredAt) cleared
  • The old pairing code becomes invalid immediately

Register Device (Admin)#

POST/api/v1/merchants/:merchantId/devices/register

Registers a device on behalf of the merchant from the portal, with the same body as the mobile self-registration. The calling admin is recorded as registeredByUserId.

Request Body:

Field Type Required Description
tpn string Yes 12-digit TPN
pairingCode string Yes Current pairing code
appVersion, osVersion string No
osPlatform enum No ANDROID | IOS

Response (201 Created):

Register Device (Admin)json
{
  "success": true,
  "data": {
    "device": { "id": "550e8400-e29b-41d4-a716-446655440002", "status": "REGISTERED", ... },
    "deviceToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "jwtNearpayDevice": null
  }
}

Unlike the other device endpoints, the device object here is the raw record (sunmiSN is omitted when empty, and serialMasked / hasSerial / hasApiKey are not added).

Errors (400): tpn and pairingCode are required, tpn must be a 12-digit numeric code, Invalid osPlatform value, Invalid TPN, Invalid pairing code, Device is not available for registration, Device already registered. Ask admin to deactivate or refresh the pairing code.


Test Connection#

POST/api/v1/merchants/:merchantId/devices/:deviceId/test-connection

Validates the device's gateway configuration without changing its status (the device-initiated POST /api/v1/device/test-connection is the one that moves REGISTERED → ACTIVE). No call is made to the device or the processor.

Response:

Test Connectionjson
{
  "success": true,
  "data": {
    "deviceId": "550e8400-e29b-41d4-a716-446655440001",
    "status": "ACTIVE",
    "gatewayType": "NMI",
    "configStatus": "VALID",
    "processorStatus": "CONNECTED",
    "validatedAt": "2026-04-14T10:05:00.000Z",
    "testDurationMs": 42
  }
}

testDurationMs is how long the validation took, not device latency. A configuration problem returns 400 with an error.code describing it (and error.gatewayType when known); an unknown device returns 404.


Device Activity#

GET/api/v1/merchants/:merchantId/devices/:deviceId/events

Recent lifecycle events for the device, newest first. Heartbeats are not included.

Query Default Description
limit 20 Max 50

Response:

Device Activityjson
{
  "success": true,
  "data": [
    {
      "id": "created:550e8400-e29b-41d4-a716-446655440001",
      "type": "CREATED",
      "title": "Device added",
      "detail": null,
      "outcome": null,
      "occurredAt": "2026-03-10T00:00:00.000Z"
    }
  ]
}

type is one of CREATED, PAIRED, CONNECTION_TEST, SESSION_STARTED, SESSION_REVOKED, ADMIN_ACTION; outcome is PASS, FAIL or null.


Reveal Serial Number#

POST/api/v1/merchants/:merchantId/devices/:deviceId/reveal-serial

Requires branches.manage. Returns the full serial and records the reveal in the audit trail.

Response: { "success": true, "data": { "serialNumber": "V2S1234567890" } }


Device Parameters#

Parameters control how a device behaves during payment flows — which transaction types are enabled, tip settings, receipt options, limits, and more.

Parameters of Dejavoo devices are managed by the provider: Update, Apply Template and Reset return 403 with code PROVIDER_PARAMETERS_NOT_EDITABLE.

Get Parameters#

GET/api/v1/merchants/:merchantId/devices/:deviceId/parameters

Example:

Get Parametersbash
curl "https://uat.auxcore.net/api/v1/merchants/8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30/devices/550e8400-e29b-41d4-a716-446655440001/parameters" \
  -H "Authorization: Bearer YOUR_JWT"

Response: the stored parameter record, using the flat field names listed under Parameter Field Names (the grouped shape is only returned to the mobile app by GET /api/v1/device/parameters).

Get Parametersjson
{
  "success": true,
  "data": {
    "id": "7d4c2b1a-9e8f-4a6b-b3c2-1d0e9f8a7b65",
    "deviceId": "550e8400-e29b-41d4-a716-446655440001",
    "tenantId": "your-tenant-id",
    "version": 5,
    "txnSaleEnabled": true,
    "txnRefundEnabled": true,
    "txnVoidEnabled": true,
    "txnPreauthEnabled": false,
    "pinVoidEnabled": false,
    "pinRefundEnabled": false,
    "payTypeTapToPayEnabled": true,
    "payTypeKeyedInEnabled": true,
    "payTypeCashEnabled": false,
    "limitPerTxn": "500.00",
    "limitDaily": "5000.00",
    "isViewAllMerchantTransaction": false,
    "signatureThreshold": "0.00",
    "allowTips": true,
    "tipPresets": [10, 15, 20, 25],
    "taxEnabled": true,
    "tax1Label": "Sales Tax",
    "tax1Value": "8.25",
    "inputFieldsConfig": [
      {
        "key": "customer_name",
        "label": "Name",
        "group": "general",
        "type": "text",
        "display": true,
        "required": false,
        "locked": false,
        "order": 1
      }
    ],
    "createdAt": "2026-03-10T00:00:00.000Z",
    "updatedAt": "2026-04-14T08:32:00.000Z"
  }
}

version increments on every update. Mobile apps use this field in the heartbeat response to detect when a full parameter refresh is needed.


Update Parameters#

PUT/api/v1/merchants/:merchantId/devices/:deviceId/parameters

Supply any subset of fields. Omitted fields retain their current values. id, deviceId, tenantId, version, createdAt and updatedAt in the body are ignored.

Request Body (flat, uses raw entity field names):

Update Parametersjson
{
  "txnSaleEnabled": true,
  "txnRefundEnabled": true,
  "txnVoidEnabled": false,
  "txnPreauthEnabled": false,
  "pinVoidEnabled": true,
  "pinRefundEnabled": true,
  "payTypeTapToPayEnabled": true,
  "payTypeKeyedInEnabled": true,
  "payTypeQrCodeEnabled": false,
  "payTypePaymentLinkEnabled": false,
  "payTypeAchTransferEnabled": false,
  "payTypeCashEnabled": true,
  "limitPerTxn": "500.00",
  "limitDaily": "5000.00",
  "limitWeekly": null,
  "limitMonthly": null,
  "isViewAllMerchantTransaction": false,
  "signatureThreshold": "25.00",
  "receiptHeaderMsg": "Welcome!",
  "receiptFooterMsg": "Thank you!",
  "receiptDisclaimer": null,
  "receiptAutoPrintEnabled": true,
  "receiptPrintMerchantCopy": true,
  "receiptSmsEnabled": true,
  "receiptEmailEnabled": true,
  "receiptSignatureCapture": false,
  "posLiteEnabled": true,
  "allowTips": true,
  "tipPresets": [10, 15, 20, 25],
  "tipMaxAmount": "100.00",
  "tipMaxPercentage": 30,
  "taxEnabled": true,
  "taxEnableRemove": false,
  "taxRemovePassProtect": false,
  "tax1Label": "Sales Tax",
  "tax1Value": "8.25",
  "tax2Label": null,
  "tax2Value": null,
  "shippingFieldsEnabled": false,
  "shippingSameAsBillingVisible": false,
  "inputFieldsConfig": [
    {
      "key": "customer_name",
      "label": "Name",
      "group": "general",
      "type": "text",
      "display": true,
      "required": true,
      "locked": false,
      "order": 1
    }
  ]
}

Response (200 OK): Updated parameter record (same flat format as GET).

Side effect: version always increments on every PUT call, even when values are unchanged.


Apply Template to Device#

Overrides the device's current parameters with values from a template, without replacing unspecified fields.

POST/api/v1/merchants/:merchantId/devices/:deviceId/parameters/apply-template

Request Body:

Apply Template to Devicejson
{
  "templateId": "550e8400-e29b-41d4-a716-446655440099"
}

Response (200 OK): Updated parameter record. Missing templateId returns 400; an unknown template returns 404 Template not found.

Only fields present in the template's parameters payload are applied. Other device-specific settings are preserved.


Reset Parameters#

Resets all parameters to factory defaults.

POST/api/v1/merchants/:merchantId/devices/:deviceId/parameters/reset

Request Body: empty

Response (200 OK): Parameters with factory default values.


Device Templates#

Templates are named snapshots of device parameters that can be applied to multiple devices.

List Templates#

GET/api/v1/merchants/:merchantId/device-templates
Query Default Description
limit 50
offset 0
manufacturer — Templates for this manufacturer plus templates with no manufacturer
deviceType — Templates for this device type plus templates with no device type

Returns templates sorted: default template first, then by creation date descending.

Response:

List Templatesjson
{
  "success": true,
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440099",
      "tenantId": "your-tenant-id",
      "merchantId": "8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30",
      "templateName": "Standard POS Config",
      "parameters": {
        "txnSaleEnabled": true,
        "txnRefundEnabled": true,
        "allowTips": true,
        "tipPresets": [10, 15, 20],
        "taxEnabled": true,
        "tax1Label": "Sales Tax",
        "tax1Value": "8.25"
      },
      "isDefault": true,
      "manufacturer": null,
      "deviceType": null,
      "createdBy": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "updatedBy": "c2b7e4a9-1d3f-4e8b-9a6c-5f0d2e7b8a13",
      "createdAt": "2026-03-01T00:00:00.000Z",
      "updatedAt": "2026-03-01T00:00:00.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "offset": 0
  }
}

Create Template#

POST/api/v1/merchants/:merchantId/device-templates

Request Body:

Field Type Required Description
templateName string Yes Display name for this template
parameters object Yes Any subset of device parameter fields (flat, raw names)
isDefault boolean No If true, replaces any existing default template
manufacturer string No Limit the template to one manufacturer
deviceType string No Limit the template to one device type

Missing templateName or parameters returns 400 templateName and parameters are required.

Example:

Create Templatebash
curl -X POST "https://uat.auxcore.net/api/v1/merchants/8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30/device-templates" \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "templateName": "Restaurant Config",
    "isDefault": true,
    "parameters": {
      "txnSaleEnabled": true,
      "txnRefundEnabled": true,
      "txnVoidEnabled": true,
      "txnPreauthEnabled": true,
      "allowTips": true,
      "tipPresets": [15, 18, 20, 25],
      "tipMaxPercentage": 40,
      "taxEnabled": true,
      "tax1Label": "Sales Tax",
      "tax1Value": "8.25",
      "receiptSignatureCapture": false
    }
  }'

Response (201 Created): Created template object.

Side effect: If isDefault: true, any previously default template for this merchant is automatically cleared.


Get Template#

GET/api/v1/merchants/:merchantId/device-templates/:templateId

Update Template#

PATCH/api/v1/merchants/:merchantId/device-templates/:templateId

Request Body (all optional): templateName, parameters, isDefault, manufacturer, deviceType.

Update Templatejson
{
  "templateName": "Updated Restaurant Config",
  "isDefault": false,
  "parameters": {
    "tipPresets": [15, 20, 25]
  }
}

Set Template as Default#

POST/api/v1/merchants/:merchantId/device-templates/:templateId/set-default

Request Body: empty

Response:

Set Template as Defaultjson
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440099",
    "isDefault": true,
    ...
  }
}

Side effect: Clears isDefault on the previously default template first, then sets this one. Only one template per merchant can be default at a time.


Delete Template#

DELETE/api/v1/merchants/:merchantId/device-templates/:templateId

Soft-deletes the template and returns { "success": true, "message": "Template deleted" }. If the deleted template was the default, no template will be marked as default until one is explicitly set.


Reference#

Enums#

DeviceManufacturer: ANDROID_PHONE | APPLE_PHONE | SUNMI

DeviceType: TAP_ON_PHONE | CARD_READER | POS_TERMINAL

DevicePaymentMode: AUXVAULT | IPOS | NEARPAY

PaymentAdjustmentType: NONE | FLAT | PERCENTAGE

DeviceStatus: PENDING | REGISTERED | ACTIVE | INACTIVE | SUSPENDED | ARCHIVED

ARCHIVED represents a soft-deleted device (deletedAt set). It's reachable only via Archive Device (or Delete Device) and leaveable only via Unarchive Device — never through Update Device Status. The other five statuses are freely inter-transitionable via Update Device Status.

There is no UNREGISTERED status — a device released by the app (POST /api/v1/device/logout) becomes INACTIVE.

DeviceOsPlatform: ANDROID | IOS

gateway is not an input. It is the gateway type of the selected merchantGatewayId (for example NMI or TsysSierra) and is null when no gateway is set.

Device Ownership (registeredByUserId)#

registeredByUserId records the merchant user whose JWT was used at POST /api/v1/device/register. It is distinct from createdBy / updatedBy, which record the portal admin who provisioned or edited the device record, and from assignedUserId, the team member the device is assigned to.

  • While the device is ACTIVE, only that user may register it again (recovering after the app lost its stored device token). The pairing code is still required.
  • Another user attempting to register an ACTIVE device gets 400 Device already registered. Ask admin to deactivate or refresh the pairing code. — deactivate it or refresh the pairing code to hand it over.
  • null on devices registered before this field existed; those reject every re-registration while ACTIVE.
  • It also drives deviceRegistration.hasActiveDevice in GET /api/v1/auth/my-merchants.

Parameter Field Names#

These flat field names are used in the GET/PUT parameter record and in the template parameters object:

Field Name Section Type
txnSaleEnabled Transactions boolean
txnRefundEnabled Transactions boolean
txnVoidEnabled Transactions boolean
txnPreauthEnabled Transactions boolean
pinVoidEnabled Require PIN boolean
pinRefundEnabled Require PIN boolean
payTypeTapToPayEnabled Payment Types boolean
payTypeKeyedInEnabled Payment Types boolean
payTypeQrCodeEnabled Payment Types boolean
payTypePaymentLinkEnabled Payment Types boolean
payTypeAchTransferEnabled Payment Types boolean
payTypeCashEnabled Payment Types boolean
limitPerTxn Limits decimal string | null
limitDaily Limits decimal string | null
limitWeekly Limits decimal string | null
limitMonthly Limits decimal string | null
isViewAllMerchantTransaction General boolean
signatureThreshold General decimal string (negative values become 0.00)
shippingFieldsEnabled Shipping boolean
shippingSameAsBillingVisible Shipping boolean
receiptHeaderMsg Receipt string | null
receiptFooterMsg Receipt string | null
receiptDisclaimer Receipt string | null
receiptAutoPrintEnabled Receipt boolean
receiptPrintMerchantCopy Receipt boolean
receiptSmsEnabled Receipt boolean
receiptEmailEnabled Receipt boolean
receiptSignatureCapture Receipt boolean
posLiteEnabled POS boolean — POS Lite: show the product cart on the POS app (default true); returned to the app as posLite.enabled. Named productCartEnabled before 2026-10-14
allowTips Tips boolean
tipPresets Tips number[] | null
tipMaxAmount Tips decimal string
tipMaxPercentage Tips number
taxEnabled Tax boolean
taxEnableRemove Tax boolean
taxRemovePassProtect Tax boolean
tax1Label Tax string | null
tax1Value Tax decimal string | null
tax2Label Tax string | null
tax2Value Tax decimal string | null
inputFieldsConfig Input Fields PaymentFormField[] | null

PaymentFormField is { key, label, group, type, display, required, order, locked? } with group one of general, avs, transaction, security, shipping and type one of text, email, phone, textarea, checkbox. locked: true means the app must not let the cashier edit the field.

Business Rules#

  1. TPN uniqueness: 12-digit numeric, globally unique. Auto-generated on create.
  2. Pairing code: 6-digit numeric, unique per tenant. Auto-generated; refreshed via dedicated endpoint.
  3. Default template: Only one template per merchant can have isDefault: true.
  4. Parameter versioning: version increments on every PUT, even when values are unchanged.
  5. Soft deletes: All deletes set deletedAt; records are retained. For devices specifically, this also sets status to ARCHIVED and is reversible via Unarchive Device.
  6. API key encryption: AES-256-GCM; never returned in responses; decrypted only at payment time.
  7. Merchant settings sync: Saving the merchant's Field Config or payment types (VT settings) pushes those rules down to every device's parameters.

Error Responses#

json
{ "success": false, "message": "Missing required fields" }
{ "success": false, "message": "Device not found" }
{ "success": false, "message": "ARCHIVED is not a valid transition target — use the archive endpoint" }
{ "success": false, "message": "Device is not archived" }
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Selected gateway is not active" } }
Status Code Meaning
200 Success
201 Created
400 Missing or invalid fields
403 Missing permission, or provider-managed parameters
404 Resource not found
422 Invalid state transition
500 Server error

Next Steps#


Need help? Contact support@auxcore.net