register_device

Register this device

act entity tenant-private since 2026-10-01

Registers an app installation by proving it holds its key, and binds it to the signed-in user in the session's org. Takes the installation's P-256 public key, a challenge from POST /v1/device/challenge and the key's signature over the installation, the challenge and the user, and optionally an Expo push token, which replaces the device's previous one. An installation bound to another user is refused until they revoke it. An org admin may enroll a managed (shared) device, which reads only.

Contract

shape
entity
authority
act
evidence
none
subscription
false
permission
any one of: self.act (the signed-in caller, about themself only; it names no other user); a deactivated caller is refused first
idempotency
natural
emits
device.registered
MCP tool
none
decision_set
approve, reject
REST
POST https://api.containertradehq.com/v1/cap/register_device

Idempotency: keyed by the contract's own inputs: the same inputs replay the first call's result

Inputs

nametyperequiredvalidation
public_pointtextrequired80 to 100 characters
The installation's P-256 public key, as its 65-byte uncompressed SEC1 point, standard base64.
platformone_ofrequiredone of ios, android
The app's platform.
app_versiontextrequired1 to 64 characters
The app's version.
challengetextrequired1 to 64 characters
A challenge POST /v1/device/challenge issued to the caller for this installation.
signaturetextrequired1 to 200 characters
The installation key's ECDSA P-256/SHA-256 signature, DER, standard base64, over the registration message (installation, challenge, caller).
expo_push_tokentextoptional1 to 255 characters
The Expo push token the app was given. A new one replaces the previous.
managedbooleanoptional
A shared or kiosk device, enrolled by an org admin: it reads only. Absent is false.
unit_idunit_idoptionaltradehq-unit-id
A unit of the session's org the device belongs to (TRA-324's yard identity).

Response

  • binding_id · string · The binding: the device's principal id.
  • installation_id · string · The installation, derived from its key.
  • managed · boolean · Whether it is a managed (shared) device.
  • push · boolean · Whether it has a live push destination.
Full JSON Schema
{
  "type": "object",
  "properties": {
    "binding_id": {
      "type": "string",
      "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$",
      "format": "uuid",
      "description": "The binding: the device's principal id.",
      "x-data-class": "operational"
    },
    "installation_id": {
      "type": "string",
      "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$",
      "format": "uuid",
      "description": "The installation, derived from its key.",
      "x-data-class": "operational"
    },
    "managed": {
      "type": "boolean",
      "description": "Whether it is a managed (shared) device.",
      "x-data-class": "operational"
    },
    "push": {
      "type": "boolean",
      "description": "Whether it has a live push destination.",
      "x-data-class": "operational"
    }
  },
  "required": [
    "binding_id",
    "installation_id",
    "managed",
    "push"
  ],
  "additionalProperties": false
}

Refusals

  • public_key_invalid · 422 · public_point is not the standard base64 of an uncompressed P-256 point on the curve
  • challenge_invalid · 422 · the challenge was not issued to the caller for this installation, is spent, or has expired; ask for a fresh one
  • signature_invalid · 422 · the signature is not the installation key's over the installation, the challenge and the caller
  • installation_bound_elsewhere · 422 · the installation is bound to another user; it can be bound again only once they revoke it
  • managed_requires_org_admin · 422 · a managed (shared) device is enrolled only by an admin of the session's org
  • managed_differs · 422 · the installation is already bound to the caller with the other managed setting; revoke it and enroll it again
  • unit_not_in_org · 422 · unit_id is not a unit of the session's org
  • push_token_invalid · 422 · expo_push_token is not an Expo push token (ExponentPushToken[...])
  • org_required · 422 · the session has selected no org to bind the device in

The platform refusals apply to every call: version, authentication, authority, validation and rate limits, each in the same envelope.

Surfaces

DesktopN
MobileF
APIF
MCPN
VoiceN
PushF
OneBoxN
OutboundN
  • Desktop: a browser holds no installation key; a device registers from the app
  • MCP: an MCP client holds no installation key
  • Voice: a key is proven by signing, which no voice surface can
  • OneBox: no document originates a device
  • Outbound: crosses to no counterparty

Events

Related

None.