---
title: Connect to ARCNM (OAuth & partners)
description: Let your product or iPaaS platform connect to ARCNM on a user's behalf with OAuth 2.1 + Dynamic Client Registration.
---

# Connect to ARCNM

There are two ways an external system authenticates to ARCNM:

| You are… | Use | Acts as |
|---|---|---|
| A script, server, or CI job for **one** org | An **[API key](./authentication.md)** (`ak_live_…`) | That org, with the key's scopes |
| A product or iPaaS platform connecting on **many users'** behalf | **OAuth 2.1** (this page) | The user who consents, in the org they pick |

OAuth is the "**Connect to ARCNM**" button: your app sends the user to
ARCNM, they pick an organization and approve a set of permissions, and you
receive a tenant-scoped access token. It's the path Zapier, Make, n8n, and
custom integrations use.

ARCNM is a standards-compliant OAuth 2.1 authorization server: PKCE is
mandatory, refresh tokens rotate on use, and tokens carry the consented org
and scopes. Most OAuth client libraries work out of the box.

---

## 1. Discover the endpoints

Fetch the authorization-server metadata (RFC 8414):

```bash
curl https://api.arcnm.io/.well-known/oauth-authorization-server
```

```json
{
  "issuer": "https://api.arcnm.io",
  "authorization_endpoint": "https://api.arcnm.io/oauth/mcp/authorize",
  "token_endpoint": "https://api.arcnm.io/oauth/mcp/token",
  "registration_endpoint": "https://api.arcnm.io/oauth/register",
  "revocation_endpoint": "https://api.arcnm.io/oauth/mcp/revoke",
  "scopes_supported": ["parts:read", "parts:write", "..."],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"],
  "code_challenge_methods_supported": ["S256"]
}
```

> MCP agent runtimes (Claude, ChatGPT, Cursor, n8n's MCP node) discover the
> MCP-specific server automatically — see [MCP](./mcp.md). The document above
> is for **direct** REST/OAuth partners.

---

## 2. Register a client

Register once with Dynamic Client Registration (RFC 7591). Registration is
open and rate-limited; the client is inert until a user consents.

```bash
curl -X POST https://api.arcnm.io/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Acme Quote Sync",
    "redirect_uris": ["https://app.acme.com/oauth/arcnm/callback"],
    "token_endpoint_auth_method": "client_secret_basic"
  }'
```

The `201` response returns your `client_id`, a `client_secret` (confidential
clients only), and a `registration_access_token` — **all shown once**:

```json
{
  "client_id": "arcnm_client_…",
  "client_secret": "cs_live_…",
  "client_secret_expires_at": 0,
  "registration_access_token": "rat_…",
  "registration_client_uri": "https://api.arcnm.io/oauth/register/arcnm_client_…"
}
```

- **Confidential client** (web app with a backend): keep the secret server-side.
- **Public client** (native, SPA, CLI): set `"token_endpoint_auth_method": "none"`.
  No secret is issued — PKCE is your proof of possession.
- Manage the client later (read / full-replace update / delete) at
  `registration_client_uri` with `Authorization: Bearer <registration_access_token>`
  (RFC 7592). A `DELETE` deprovisions it (`204`).

You can also register from the dashboard: **Settings → Connected apps**.

---

## 3. Authorize (PKCE)

Generate a PKCE `code_verifier` + S256 `code_challenge`, then send the user to:

```
GET https://api.arcnm.io/oauth/mcp/authorize
      ?response_type=code
      &client_id=arcnm_client_…
      &redirect_uri=https://app.acme.com/oauth/arcnm/callback
      &scope=parts:read%20parts:calculations:read
      &state=<csrf>
      &code_challenge=<S256>
      &code_challenge_method=S256
```

ARCNM authenticates the user (login + MFA as needed), shows a branded
consent screen with **your app's name and logo**, and the user picks the
organization to grant access to. On approval the browser returns to your
`redirect_uri` with `?code=…&state=…`. `redirect_uri` must **exactly match**
one you registered.

---

## 4. Exchange the code for tokens

```bash
curl -X POST https://api.arcnm.io/oauth/mcp/token \
  -u "arcnm_client_…:cs_live_…" \
  -d grant_type=authorization_code \
  -d code=<code> \
  -d redirect_uri=https://app.acme.com/oauth/arcnm/callback \
  -d code_verifier=<code_verifier>
```

```json
{
  "access_token": "eyJ…",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "eyJ…",
  "scope": "parts:read parts:calculations:read"
}
```

Call the REST API with `Authorization: Bearer <access_token>`. The token is
pinned to the consented org and scopes — no `X-Org-Slug` needed, and it can
never act outside what the user approved.

Public clients omit `-u` and send `client_id` as a form field instead; the
`code_verifier` is the only credential.

---

## 5. Refresh

Access tokens are short-lived (~15 min). Refresh tokens are **single-use and
rotate** — each refresh returns a new refresh token; the old one is dead. A
replayed refresh token fails closed.

```bash
curl -X POST https://api.arcnm.io/oauth/mcp/token \
  -u "arcnm_client_…:cs_live_…" \
  -d grant_type=refresh_token \
  -d refresh_token=<refresh_token>
```

Users can revoke your app any time from **Settings → Authorized apps**, and
you can revoke a refresh token at the `revocation_endpoint` (RFC 7009).

---

## Scopes

Request the least privilege you need; the user can narrow it further on the
consent screen. See [Authentication](./authentication.md#scopes) for the full
catalog — common ones: `parts:read`, `parts:calculations:read`,
`uploads:write`, `jobs:read`, `webhooks:read`, `webhooks:write`.

---

## Receive events

Pair OAuth (or an API key) with [Webhooks](./webhooks.md): subscribe to
`calculation.succeeded`, `wallet.*`, and more, signed with the Standard
Webhooks scheme. A token with `webhooks:write` can self-subscribe — the
REST-Hooks pattern iPaaS platforms expect.

---

## See also

- [Authentication](./authentication.md) — API keys, scopes, headers.
- [Webhooks](./webhooks.md) — events, signatures, the event catalog.
- [MCP](./mcp.md) — connecting agent runtimes (Claude, ChatGPT, …).
