Skip to main content
The Builder API exposes a set of user management endpoints scoped to your app tenant. These endpoints let your backend provision the user records that PymtHouse needs to issue user-scoped JWTs, attribute usage to individuals, and manage per-user billing entitlements. All endpoints require a confidential M2M client for authentication. See Machine access for the two auth patterns (Bearer token and HTTP Basic auth).

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

Required M2M scopes per operation:

List users

Returns all provisioned users for the app tenant.

Create or upsert a user

This operation is idempotent: sending the same 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

The upsert uses a database-level ON CONFLICT DO UPDATE to avoid duplicate-key races under concurrent provisioning. It is safe to call from multiple backend instances simultaneously. New users are auto-subscribed to the Starter plan on first provision.

Update user attributes

Update attributes on an existing user record. The request body follows the same shape as the create/upsert body.

Deactivate a user

Sets 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.
GET returns the list of active API keys for the user. POST creates a new key. Response includes the full pmth_* secret (shown once only):
DELETE with ?keyId=<uuid> revokes the key immediately. Exchange a per-user API key for a short-lived JWT:
See API keys for the full exchange flow.

App-level API keys

App-level API keys (tied to a subscription) are managed separately:
Auth: provider dashboard session. These keys are suitable for integrations where a single credential covers the entire app rather than individual users.

User allowances and entitlements

Per-user USD micro allowances are managed via the allowances endpoint:
And balance is checked at:
See Allowances for the full reference.

User subscription status

Read the OpenMeter subscription state for a specific end-user:
Returns the user’s active plan subscription (Starter or a paid checkout plan), including status, period, and entitlement details.

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.
For high-volume initial imports, acquire one machine token (client credentials grant) and reuse it across the loop rather than re-authenticating per request.

Error responses


Key design decisions

  1. externalUserId as 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.
  2. Upsert semantics by default on POST. Idempotent provisioning makes it safe to call from retry logic or concurrent workers.
  3. Soft delete only (status: inactive). Hard-deleting a user record would orphan historical usage records. Keeping the record preserves the join between usage_records.user_id and app_users.
  4. 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 externalUserId during 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 externalUserId values are stable and unique within your app.
  • Use GET .../usage/balance before 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.