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

# Authentication

Method supports two ways to authenticate requests: **API keys** and **OAuth 2.0 client
credentials**. Both are sent as a Bearer token in the `Authorization` header of every request, and
both resolve to the same team, so the rest of the API behaves identically.

| | API keys | OAuth |
| - | - | - |
| Credential | A long-lived secret key (`sk_…`) | A `client_id` and `client_secret` exchanged for a short-lived access token (`oat_…`) |
| Expiry | Never expires | Access tokens expire after 1 hour |
| Access | Full access to your team | Constrained to the scopes granted to your client |
| Setup | Copy the key from the Dashboard | Create a client, then implement the token exchange |

Use an API key to get started quickly, or where a single trusted service calls Method. Use OAuth
when you want short-lived credentials that expire on their own, or when you want to restrict an
integration to a subset of the API.

## API keys

An API key identifies your team. Secret API keys have the prefix `sk_`, and your team has a separate
key for each [environment](/2026-03-30/reference/environments). Keys are available under the Keys section in the
[Method Dashboard](https://dashboard.methodfi.com), where you can also rotate them.

API keys do not expire and carry full access to your team, so treat them as sensitive credentials:
store them in a secrets manager, never in client-side code or version control.

Get started by creating your account in the [Method Dashboard](https://dashboard.methodfi.com) or
[connect](https://methodfi.com/contact-us) with our team.

## OAuth

Method supports [OAuth 2.0 Client Credentials](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4)
as an alternative to API keys. You exchange a `client_id` and `client_secret` for a short-lived
access token, then use that token on API requests in place of an API key.

1. Create an OAuth client in the [Method Dashboard](https://dashboard.methodfi.com) to get a `client_id` and `client_secret`.
2. Exchange them at `POST /oauth/token` for an access token, valid for 1 hour.
3. Call the Method API with `Authorization: Bearer <access_token>`.
4. When the token expires, request a new one the same way.

### Credentials

| Credential | Format | Notes |
| - | - | - |
| `client_id` | `ocl_…` | Identifies your integration. Not a secret. Safe to log and reference in support requests. |
| `client_secret` | `ocs_…` | Shown exactly once at issuance. Store it in a secrets manager. Method cannot retrieve it. |

Clients and secrets are managed under the OAuth section in the
[Method Dashboard](https://dashboard.methodfi.com), where you can mint new
secrets and disable existing ones. Each environment has its own clients and secrets.

<Warning>
  If you lose a `client_secret`, mint a new one from the Dashboard. Method cannot recover the original value.
</Warning>

### Getting an access token

Send a `POST` request to `/oauth/token` with a `application/x-www-form-urlencoded` body containing
`grant_type=client_credentials`. Authenticate with your client credentials using either HTTP Basic
auth or the request body.

<CodeGroup>
  ```bash HTTP Basic auth theme={null}
  curl https://production.methodfi.com/oauth/token \
    -u "ocl_AbC123:ocs_XYZ456" \
    -d "grant_type=client_credentials"
  ```

  ```bash Credentials in body theme={null}
  curl https://production.methodfi.com/oauth/token \
    -d "grant_type=client_credentials" \
    -d "client_id=ocl_AbC123" \
    -d "client_secret=ocs_XYZ456"
  ```
</CodeGroup>

HTTP Basic auth is recommended, and is the default for most OAuth client libraries. Use the base
URL for your [environment](/2026-03-30/reference/environments).

```json theme={null}
{
  "access_token": "oat_7Hk94r83482csdcK2mQx9vTz",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "entities:read entities:write accounts:read"
}
```

| Field | Description |
| - | - |
| `access_token` | The bearer token (`oat_…`). Treat it as a secret. |
| `token_type` | Always `Bearer`. |
| `expires_in` | Lifetime in seconds (3600 = 1 hour). |
| `scope` | Space-delimited scopes this token carries. |

### Token endpoint errors

The token endpoint uses the standard OAuth error format rather than the Method error envelope.

```json theme={null}
{ "error": "invalid_client", "error_description": "Client authentication failed." }
```

| HTTP | `error` | Cause |
| - | - | - |
| 400 | `invalid_request` | Missing or malformed parameters, such as an absent `grant_type`. |
| 400 | `unsupported_grant_type` | A `grant_type` other than `client_credentials`. |
| 400 | `invalid_scope` | Requested scope not granted to your client. |
| 401 | `invalid_client` | Client authentication failed. |
| 429 | `too_many_requests` | Rate limit exceeded. Retry after the `Retry-After` header. |

### Scopes

Scopes follow `<resource>:<action>`, where the action maps to the HTTP method:

| HTTP method | Action |
| - | - |
| `GET` | `read` |
| `POST`, `PUT`, `PATCH`, `DELETE` | `write` |

For example, `entities:read` allows `GET /entities/…` and `entities:write` allows `POST /entities`.

Your client is granted a set of scopes by Method. By default a token carries all of them. To
request a token with fewer scopes, pass a space-delimited `scope` parameter:

```bash theme={null}
curl https://production.methodfi.com/oauth/token \
  -u "ocl_AbC123:ocs_XYZ456" \
  -d "grant_type=client_credentials" \
  -d "scope=entities:read accounts:read"
```

Requesting a scope your client has not been granted returns `400 invalid_scope`.

### Calling the API with an access token

Send the access token in the `Authorization` header. Everything else about the API is unchanged.

```bash theme={null}
curl https://production.methodfi.com/entities \
  -H "Method-Version: 2026-03-30" \
  -H "Authorization: Bearer oat_7Hk94r83482csdcK2mQx9vTz"
```

Two errors are specific to token-based requests:

* **401** — the token is missing, invalid, expired, or revoked. Request a new token and retry.
* **403** with `sub_type: INSUFFICIENT_SCOPE` — the token does not carry the scope this endpoint requires.

```json theme={null}
{
  "success": false,
  "data": {
    "error": {
      "type": "INVALID_REQUEST",
      "code": 403,
      "sub_type": "INSUFFICIENT_SCOPE",
      "message": "Your access token is missing the required scope 'entities:write' for POST /entities."
    }
  },
  "message": "Your access token is missing the required scope 'entities:write' for POST /entities."
}
```

### Token lifecycle

* **Cache the token** and reuse it for its full lifetime. Do not request a new token per API call.
* **Renew shortly before expiry**, for example 60 seconds early, to avoid a `401` at the boundary.
  On an unexpected `401`, request a new token once and retry.
* **There are no refresh tokens.** This is by design for the client credentials grant
  ([RFC 6749 §4.4.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.3)). Renewal is the
  same `POST /oauth/token` call again.

<Note>
  The token endpoint is [rate limited](/2026-03-30/reference/rate-limiting).
</Note>

### Secret rotation

Rotate your `client_secret` from the [Method Dashboard](https://dashboard.methodfi.com) for
routine rotation or suspected exposure. Your `client_id` never changes.

1. Mint a new secret. Both the new and existing secrets remain valid.
2. Deploy the new secret on your own schedule, with no downtime.
3. Disable the old secret once you have confirmed cutover.

If a secret is compromised, disable it immediately.

<RequestExample>
  ```bash cURL theme={null}
  curl https://production.methodfi.com/accounts \
    -H "Method-Version: 2026-03-30" \
    -H "Authorization: Bearer sk_WyZEWVfTcH7GqmPzUPk65Vjc"
  ```

  ```javascript Node.js theme={null}
  const { Method, Environments } = require('method-node');

  const method = new Method({
    apiKey: 'sk_WyZEWVfTcH7GqmPzUPk65Vjc',
    env: Environments.production,
  });

  const accounts = await method.accounts.list();
  ```

  ```python Python theme={null}
  from method import Method

  method = Method(env='production', api_key='sk_WyZEWVfTcH7GqmPzUPk65Vjc')

  accounts = method.accounts.list()
  ```
</RequestExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.