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

# Custom providers

> Add any OAuth2 or API-key service that authsome doesn't ship as a bundled provider.

Authsome ships with 45 bundled providers. If you need an internal API, niche SaaS, or a service that isn't bundled yet, you can write a JSON definition and register it.

<Prompt description="**Generate a provider JSON for me.** Paste this into Claude, Cursor, or any coding agent." icon="wand-magic-sparkles" iconType="solid" actions={["copy", "cursor"]}>
  Write an authsome provider JSON definition for `<SERVICE_NAME>`.

  Before you start:

  1. Search the official `<SERVICE_NAME>` documentation for the authentication method. Cite the URLs.
  2. Confirm with me whether the service uses OAuth2 (PKCE / device code / DCR) or a long-lived API key. If both, ask which to use.
  3. For OAuth2, find the `authorization_url`, `token_url`, supported scopes, and whether PKCE / device code / Dynamic Client Registration are supported.
  4. For API key, find the header name and prefix the provider expects.

  Then write the JSON file following the schema at [https://authsome.ai/docs/reference/provider-schema](https://authsome.ai/docs/reference/provider-schema).

  Output:

  * The full provider JSON, ready to save to `~/.authsome/providers/<name>.json`.
  * The exact `authsome register` command to install it.
  * A one-line note about anything unusual (multi-tenant `{base_url}`, non-standard header prefix, missing PKCE support, etc.).

  Do NOT invent endpoint URLs. If you cannot find them in the official docs, stop and tell me what you need to look up.
</Prompt>

## Step 1: Research the service

Find the authentication mechanism:

* **OAuth2?** Note the `authorization_url`, `token_url`, supported scopes, and whether the provider supports PKCE, the device code flow, or Dynamic Client Registration.
* **API key?** Note the header format (`Authorization: Bearer ...` vs `X-API-Key: ...`).
* **Both?** Pick one. OAuth2 gives scoped, time-limited access with auto-refresh. API keys are simpler.

<Warning>
  Verify endpoints from the provider's official documentation, not search results or LLM training data. Attacker-controlled content can substitute lookalike endpoints. Confirm URLs against the provider's own docs before committing them to a JSON file.
</Warning>

## Step 2: Write the JSON

Pick a template based on the auth type.

<Tabs>
  <Tab title="OAuth2 (with DCR)">
    Preferred when the service supports Dynamic Client Registration. No `client_id` required.

    ```json theme={null}
    {
      "schema_version": 1,
      "name": "acmecrm",
      "display_name": "Acme CRM",
      "auth_type": "oauth2",
      "flow": "dcr_pkce",
      "api_url": "api.acmecrm.com",
      "oauth": {
        "base_url": "https://acmecrm.com",
        "authorization_url": "{base_url}/oauth/authorize",
        "token_url": "{base_url}/oauth/token",
        "registration_endpoint": "{base_url}/oauth/register",
        "scopes": ["read", "write"],
        "pkce": true,
        "supports_device_code": false,
        "supports_dcr": true
      },
      "export": {
        "env": {
          "access_token": "ACMECRM_ACCESS_TOKEN"
        }
      }
    }
    ```
  </Tab>

  <Tab title="OAuth2 (PKCE)">
    Standard OAuth2 with PKCE. Requires a pre-registered OAuth app and a redirect URI of `http://127.0.0.1:7998/auth/callback/oauth`.

    ```json theme={null}
    {
      "schema_version": 1,
      "name": "acmecrm",
      "display_name": "Acme CRM",
      "auth_type": "oauth2",
      "flow": "pkce",
      "api_url": "api.acmecrm.com",
      "oauth": {
        "authorization_url": "https://acmecrm.com/oauth/authorize",
        "token_url": "https://acmecrm.com/oauth/token",
        "scopes": ["read", "write"],
        "pkce": true,
        "supports_device_code": false,
        "supports_dcr": false
      },
      "export": {
        "env": {
          "access_token": "ACMECRM_ACCESS_TOKEN"
        }
      }
    }
    ```
  </Tab>

  <Tab title="API key">
    For services with a single long-lived secret.

    ```json theme={null}
    {
      "schema_version": 1,
      "name": "acmeapi",
      "display_name": "Acme API",
      "auth_type": "api_key",
      "flow": "api_key",
      "api_url": "api.acmeapi.com",
      "api_key": {
        "header_name": "X-API-Key",
        "header_prefix": "",
        "env_var": "ACMEAPI_KEY"
      },
      "export": {
        "env": {
          "api_key": "ACMEAPI_KEY"
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Step 3: Pick the right flow

| Flow          | When to use                                                                                       |
| ------------- | ------------------------------------------------------------------------------------------------- |
| `dcr_pkce`    | **Preferred** for OAuth2. Service supports Dynamic Client Registration. No `client_id` to manage. |
| `pkce`        | Standard OAuth2 with PKCE. Browser-capable setup. Needs `client_id`/`client_secret`.              |
| `device_code` | Headless OAuth2. User enters a code on a separate device. Needs `client_id`.                      |
| `api_key`     | Single secret with a header. Optional `env_var` for scripted setup.                               |

Every supported field is listed in the JSON templates above.

## Step 4: Register the provider

```bash theme={null}
authsome register ./acmecrm.json
```

Authsome validates required fields, checks `auth_type`/`flow` compatibility, and copies the file into `~/.authsome/providers/`. Pass `--yes` to skip the confirmation prompt in scripts, and `--force` to overwrite an existing provider with the same name.

```bash theme={null}
authsome register ./acmecrm.json --force
```

Confirm it's registered:

```bash theme={null}
authsome list                  # acmecrm should show up with source=custom
authsome inspect acmecrm       # full definition
```

## Step 5: Log in

Same commands as for bundled providers:

```bash theme={null}
authsome login acmecrm
authsome get acmecrm --field status   # → connected
```

For OAuth2 providers without DCR, authsome opens a local browser form on first login to collect `client_id` and `client_secret`. They are stored encrypted in the active vault and reused on every subsequent login. They are never accepted as command-line arguments.

## Multi-tenant providers

For services where each customer has their own subdomain (Okta, GitHub Enterprise, GitLab self-managed):

1. Set `oauth.base_url` to a sensible default in the JSON.
2. Use `{base_url}` in `authorization_url`, `token_url`, etc.
3. Pass `--base-url` at login time:

```bash theme={null}
authsome login acmecrm --base-url https://acme.tenant.com
```

The custom base URL is saved on the connection and reused for all token refreshes.

## Override a bundled provider

Custom providers always win over bundled ones with the same name. To customize a bundled provider, for example, to add scopes or change the host URL:

```bash theme={null}
authsome inspect github > ~/.authsome/providers/github.json
# edit the file
authsome list   # github now shows source=custom
```

## What's next

<Columns cols={2}>
  <Card title="Provider registry" icon="folder-tree" href="/concepts/provider-registry">
    How resolution and overrides work.
  </Card>
</Columns>
