Identity model
PymtHouse maps your user identifiers using two distinct id spaces:
Never construct Builder API paths with internal PymtHouse IDs — always use
externalUserId in paths and request bodies.
Base path
{clientId} is the public app_… client id. The tenant boundary is enforced server-side: the authenticated M2M client must belong to the same app as the clientId in the path. A mismatch returns 404.
Prerequisites
List users
Create or upsert a user
externalUserId again updates the existing record rather than creating a duplicate. New users are automatically subscribed to the app’s Starter plan.
Request body
Example
Update user attributes
Deactivate a user
status: inactive on the user. Records are not hard-deleted — deactivation preserves the record for usage attribution and audit purposes. You can reactivate a deactivated user by calling POST/PUT with status: active.
Per-user API keys
Long-lived opaque API keys (pmth_*) can be issued per-user and exchanged for short-lived JWTs or signer sessions without repeating device login.
pmth_* secret (shown once only):
?keyId=<uuid> revokes the key immediately.
Exchange a per-user API key for a short-lived JWT:
App-level API keys
App-level API keys (tied to a subscription) are managed separately:User allowances and entitlements
Per-user USD micro allowances are managed via the allowances endpoint:User subscription status
Read the OpenMeter subscription state for a specific end-user:Bulk provisioning
There is no batch endpoint. For bulk provisioning, loop over your user set and call POST for each user. The upsert semantics make it safe to re-run the loop — already-provisioned users will be updated in place.Error responses
Key design decisions
externalUserIdas the join key, not an internal ID. This eliminates the need for integrators to store PymtHouse-internal IDs and removes the risk of foreign-key coupling between two systems.- Upsert semantics by default on POST. Idempotent provisioning makes it safe to call from retry logic or concurrent workers.
- Soft delete only (
status: inactive). Hard-deleting a user record would orphan historical usage records. Keeping the record preserves the join betweenusage_records.user_idandapp_users. - Auto-Starter subscription on provision. New users start with the Starter plan allowance immediately after
POST /users, without requiring a separate subscription step.
Implementation tasks
- Call POST with
externalUserIdduring your user creation flow so the PymtHouse record is ready before the first JWT mint. - Implement a lightweight reconciliation job that calls POST/PUT for users whose attributes have changed in your system.
- When deactivating users in your system, call DELETE on the PymtHouse side to prevent new JWT issuance.
- Ensure your
externalUserIdvalues are stable and unique within your app. - Use
GET .../usage/balancebefore allowing signed requests to verify the user has remaining entitlement. - For high-concurrency environments, use the Bearer token pattern (one token per batch) rather than re-authenticating on each call.