Core Concepts

Identity Types

A decision is always routed to an identity, not to a specific device. Noxy supports four identity types so you can match the way your product already thinks about its users.

The four types

TypeWire stringLogical idBest when…
EmailemailEmail addressYou already authenticate users by email.
PhonephoneE.164 string (e.g. +15551234567)SMS-first products or consumer apps with phone-based sign-in.
User iduser_idAn opaque string you controlYou have your own user system and want to keep PII off Noxy.
WalletwalletEVM address (e.g. 0x742d…)Your users sign in with a crypto wallet (EOA or smart contract wallet).

One identity, many devices

A single identity can register many devices: a phone, a laptop, a Telegram session, multiple browser tabs. When your agent routes a decision, the relay encrypts and delivers a separate ciphertext for each device the identity has registered. The first device to send an outcome closes the decision for that identity.

Outcome is identity-wide. You query outcomes by (decision_id, identity_id). Polling does not care which of the user's devices answered.

Choosing a type

  • Already have user accounts? Use user_id with your existing primary key. This keeps email and phone off the relay entirely.
  • Consumer flows where the channel is the identity? Use email or phone directly. They map cleanly to how you already address the user.
  • Users authenticate with a wallet? Use wallet. The Client SDKs also accept both EOAs and smart contract wallets with a custom signer.

Email, phone, and user_id

Email, phone, and user_id identities use a fixed registration HMAC derived from APP_SIGNING_SECRET — there is no separate per-user signer to provide. You only need the type and the logical id string.

// Browser SDK — email identity
identity: {
  identityType: NOXY_IDENTITY_TYPE.EMAIL,
  identityId: 'user@example.com',
}

// Android / iOS / Telegram bot — same idea
identity: {
  identityType: NOXY_IDENTITY_TYPE.USER_ID,
  identityId: 'internal-user-abc123',
}

Wallet identities

Wallet identities are supported in addition to the web2 types above: the device registration signature can be produced by the wallet itself (instead of the standard HMAC). Both EOAs and smart contract wallets are supported — pass a signer callback to the Client SDK and it will request a signature when needed.

// Browser SDK — EOA wallet identity
identity: {
  type: 'eoa',
  address: '0x…',
  signer: async (data) => wallet.signMessage({ message: { raw: data } }),
}

Tip. Use stable strings. The relay partitions devices and decisions by (app_id, identity_type, identity_id), so changing the id string (e.g. lower-casing an email after the fact) effectively orphans previously registered devices.

Looking up devices for an identity

You normally do not need to address individual devices — the Agent SDK fans the decision out for you. When you do (auditing, debugging, choosing a single target device), call GetIdentityDevices with the logical id and you receive each device's id and public keys.

See GetIdentityDevices in the API reference.

Switching identity later

Identity bindings are immutable on a registered device. If a user moves from a phone-based identity to a wallet identity, register a new device under the new identity type and revoke the old one with revokeDevice().