> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pymthouse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Provision a user and mint a scoped access token in under ten minutes.

This guide walks through the minimum steps to integrate a backend service with PymtHouse. By the end you will have:

1. A machine token issued via client credentials (RFC 6749 §4.4).
2. An end-user provisioned in your app's tenant.
3. A user-scoped JWT with `sign:job` ready to pass to PymtHouse services.

## Prerequisites

* A registered developer app with a **confidential M2M client** (`m2m_…` id and `pmth_cs_…` secret). See [Client model](/integration/client-model) for how these relate.
* `curl` and `jq` available locally, or any HTTP client.
* Your PymtHouse deployment URL (local: `http://localhost:3001`).

```bash theme={null}
export BASE_URL="https://your-pymthouse.example"
export M2M_ID="m2m_yourClientId"
export M2M_SECRET="pmth_cs_yourSecret"
export PUBLIC_CLIENT_ID="app_yourClientId"
```

<Tip>
  For local development, `BASE_URL` is `http://localhost:3001`. The M2M and public client IDs are created from the developer dashboard or by running `npm run oidc:seed` during setup.
</Tip>

## Step 1 — Obtain a machine token

Exchange your M2M client credentials for a short-lived access token. The token endpoint follows OIDC discovery and is stable at `{issuer}/token`.

```bash theme={null}
MACHINE_TOKEN=$(curl -sS \
  -d "grant_type=client_credentials" \
  -d "client_id=${M2M_ID}" \
  -d "client_secret=${M2M_SECRET}" \
  -d "scope=users:write users:token" \
  "${BASE_URL}/api/v1/oidc/token" | jq -r '.access_token')

echo "Machine token: ${MACHINE_TOKEN:0:40}..."
```

<Note>
  Request only the scopes your operation requires. `users:write` is needed for provisioning; `users:token` is needed for minting user JWTs. Scope assignment is managed on the M2M client; ask the platform admin if a scope is missing.
</Note>

## Step 2 — Provision an end-user

Create or upsert a user record linked to your own user identifier (`externalUserId`). This call is **idempotent**: sending the same `externalUserId` again returns the existing record rather than creating a duplicate.

```bash theme={null}
curl -sS \
  -H "Authorization: Bearer ${MACHINE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "externalUserId": "user-123",
    "email": "alice@example.com",
    "status": "active"
  }' \
  "${BASE_URL}/api/v1/apps/${PUBLIC_CLIENT_ID}/users" | jq .
```

A `200` response confirms the user exists in the PymtHouse tenant. Store nothing from this response — `externalUserId` is your stable join key.

## Step 3 — Mint a user-scoped JWT

Issue a short-lived access token on behalf of the user. This token carries the user's identity as its `sub` and is scoped to the requested capability.

```bash theme={null}
USER_JWT=$(curl -sS \
  -H "Authorization: Bearer ${MACHINE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "scope": "sign:job" }' \
  "${BASE_URL}/api/v1/apps/${PUBLIC_CLIENT_ID}/users/user-123/token" \
  | jq -r '.access_token')

echo "User JWT: ${USER_JWT:0:40}..."
```

This token:

* Has `sub` = the PymtHouse app-user record id.
* Has `client_id` / `azp` = the **public** `app_…` client id.
* Is bounded to the scopes configured on the public client — `sign:job` must be in its `allowed_scopes`.

Pass this token in an `Authorization: Bearer` header to downstream PymtHouse services.

## What's next

<CardGroup cols={2}>
  <Card title="Client model" icon="diagram-project" href="/integration/client-model">
    Deep-dive into the two-client pattern, scope table, and billing mode.
  </Card>

  <Card title="Machine access" icon="server" href="/integration/machine-access">
    Alternative auth patterns and how to keep machine tokens short-lived.
  </Card>

  <Card title="Device flow" icon="mobile-screen" href="/integration/device-flow">
    Add browser-authenticated device sessions for CLI and limited-input clients.
  </Card>

  <Card title="Usage API" icon="chart-bar" href="/integration/usage-api">
    Query fee totals and per-user attribution for billing dashboards.
  </Card>
</CardGroup>
