Use a machine-to-machine (M2M) application when a workload must authenticate without a person: backend-to-backend calls, jobs, CI automation, or agents. Authdog registers a confidential OIDC client for the environment and uses OAuth 2.0 `client_credentials`; no browser session or interactive sign-in is involved.

## Create an M2M application

In the [Authdog console](https://console.authdog.com):

1. Create a new project or application.
2. Choose **Machine-to-machine** as its type.
3. Enter a descriptive name and, optionally, what the workload will access.
4. Create the application.
5. Copy the generated client ID and client secret before closing the dialog.

Creation provisions a default environment and registers a client authorized only for `client_credentials`, using `client_secret_basic` authentication. The client secret is shown once.

Use a separate M2M application per workload and environment. This gives each workload an independent credential lifecycle and avoids sharing production secrets with development jobs.

## Discover the token endpoint

Use the OIDC metadata for the environment or identity host and read its `token_endpoint`. Authdog's token endpoint path is `/oauth2/token`; discovery avoids hard-coding a deployment origin and continues to work with an environment [custom domain](/docs/custom-domains).

## Exchange credentials for a token

Send an `application/x-www-form-urlencoded` request. Client ID and secret use HTTP Basic authentication:

```bash
curl -X POST "$TOKEN_ENDPOINT" \
  -u "$AUTHDOG_CLIENT_ID:$AUTHDOG_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials"
```

Successful responses contain `access_token`, `token_type` (`Bearer`), `expires_in`, and scope `client_credentials`. `expires_in` comes from the registered client's access-token lifetime. Client-credentials exchanges return an access token only, not a refresh token.

## Call a protected service

Send the access token as a bearer token:

```http
Authorization: Bearer <access_token>
```

The receiving service must validate authentication and then enforce authorization for the operation. A valid machine token identifies a caller; it does not by itself grant every action.

## Security guidance

- Store client secrets in a secret manager, never source control, browser code, command history, or logs.
- Keep token exchange and API calls in trusted workloads.
- Use one client per workload and least-privilege authorization around the resources it calls.
- Cache access tokens only in memory and only until shortly before `expires_in`.
- On suspected exposure, stop using the client and replace its credentials. Do not wait for leaked access tokens to expire.
- Never use a human user's cookie or personal token for unattended automation.

The token endpoint rejects inactive or unknown clients, incorrect authentication methods, bad secrets, and clients not authorized for `client_credentials`.

## Operational notes

- Refresh by repeating the client-credentials exchange; no refresh token is issued.
- Add jitter when many instances refresh so they do not all exchange credentials simultaneously.
- Record client ID and workload name in audit context, but redact secrets and access tokens.
- Test development and production independently because clients and signing context are environment-scoped.
- If application creation succeeds but credential generation fails, create or inspect the client under **Security → Clients** in the console.

## Service accounts

Service accounts represent organization-owned automation with explicit scopes.
Public REST endpoints support lifecycle management:

- `GET /v1/service-accounts`
- `GET /v1/service-accounts/{id}`
- `POST /v1/service-accounts`
- `DELETE /v1/service-accounts/{id}`

Create with a descriptive `name`, optional `description`, and least-privilege
`scopes`. Response includes service-account metadata, `clientId`, and
`clientSecret`. Secret is credential material; capture it from creation
response, store it in a secret manager, and never expose it to browser code.
Deleting service account is revocation path—use separate account per workload
so one compromise does not require rotating unrelated automation.

## Personal access tokens

Personal access token (PAT) delegates current user's access to scripts and
developer tooling. It is not preferred for shared services because ownership
and lifecycle remain attached to person.

- `GET /v1/personal-access-tokens`
- `POST /v1/personal-access-tokens`
- `POST /v1/personal-access-tokens/{id}/revoke`

Create request accepts `name`, optional `expiresAt`, and optional `scopes`.
Creation response is only operation that returns `fullToken`; later list
responses expose prefix and metadata, not secret. Set expiry, choose narrow
scopes, and revoke token when task ends or owner leaves.

Use:

- **M2M application** for OAuth-compatible workload tokens with bounded
  lifetime.
- **Service account** for organization-owned automation managed through
  Authdog API.
- **PAT** for one person's local script or developer tool.

## Related

- [Backend requests](/docs/backend#service-to-service-m2m) — accepting machine tokens
- [Sessions and tokens](/docs/concepts/sessions-tokens#service-to-service-tokens) — token model
- [Authorization](/docs/concepts/authorization) — enforcing access after authentication
- [Deployments](/docs/deployments) — environment isolation
- [Security](/docs/security) — key and credential guidance
