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

# Authentication

> Authenticate v2 requests with client credentials or OAuth bearer tokens.

# Authentication

The v2 API supports two authentication flows. Call your **own** Vantr account from a trusted server with **client credentials**, or let **other merchants** connect their accounts to your app with the **OAuth authorization code flow**.

<Columns cols={2}>
  <Card title="Client credentials" icon="server" type="check">
    Your own account, called from a backend you control. One request, no browser, no user. **Covered on this page.**
  </Card>

  <Card title="Authorization code + PKCE" icon="users" href="/guides/oauth-authorization-code" type="info">
    A third party connects other merchants' accounts. Browser redirect plus a per-merchant consent screen. **See the guide →**
  </Card>
</Columns>

<Warning>
  Client secrets are passwords for your integration. Keep them server-side and rotate them if they are ever exposed.
</Warning>

## Choose an auth method

<Tabs>
  <Tab title="Basic auth" icon="key-round">
    Use HTTP Basic auth with the client ID as the username and the client secret as the password.

    <CodeGroup>
      ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -u "$CLIENT_ID:$CLIENT_SECRET" \
        "https://api.vantr.ai/v2/products?limit=25"
      ```

      ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}}
      const credentials = Buffer
        .from(`${process.env.CLIENT_ID}:${process.env.CLIENT_SECRET}`)
        .toString('base64');

      const response = await fetch('https://api.vantr.ai/v2/products?limit=25', {
        headers: {
          Authorization: `Basic ${credentials}`,
        },
      });
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
      import os
      import requests

      response = requests.get(
          "https://api.vantr.ai/v2/products",
          params={"limit": 25},
          auth=(os.environ["CLIENT_ID"], os.environ["CLIENT_SECRET"]),
          timeout=20,
      )
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Client headers" icon="panel-top">
    Use headers when your HTTP client cannot conveniently send Basic auth.

    ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl \
      -H "x-client-id: $CLIENT_ID" \
      -H "x-client-secret: $CLIENT_SECRET" \
      "https://api.vantr.ai/v2/products?limit=25"
    ```
  </Tab>

  <Tab title="Bearer token" icon="ticket-check">
    Exchange the `client_credentials` grant at `/oauth/token` for a short-lived access token, then pass it on v2 requests. This keeps your `client_secret` off individual API calls.

    <CodeGroup>
      ```bash Token request theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -u "$CLIENT_ID:$CLIENT_SECRET" \
        -d "grant_type=client_credentials" \
        -d "scope=products.read categories.read locations.read" \
        "https://api.vantr.ai/oauth/token"
      ```

      ```bash API request theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -H "Authorization: Bearer $ACCESS_TOKEN" \
        "https://api.vantr.ai/v2/categories/tree"
      ```
    </CodeGroup>

    <Note>
      To act on **another merchant's** account instead of your own, use the `authorization_code` grant — see [Authorize a user (OAuth)](/guides/oauth-authorization-code).
    </Note>
  </Tab>
</Tabs>

## Token request

Use `application/x-www-form-urlencoded` for OAuth token calls.

<ParamField body="grant_type" type="string" required>
  Use `client_credentials`, `authorization_code`, or `refresh_token`.
</ParamField>

<ParamField body="scope" type="string">
  Space-separated scopes. Required for `client_credentials` and `authorization_code`; optional on refresh when you want to narrow the refreshed access token.
</ParamField>

<ParamField body="code" type="string">
  Authorization code returned from `/oauth/authorize`. Required for `authorization_code`.
</ParamField>

<ParamField body="code_verifier" type="string">
  PKCE verifier that matches the original `code_challenge`. Required for `authorization_code`.
</ParamField>

<ResponseField name="access_token" type="string" required>
  Opaque bearer token to pass in the `Authorization` header.
</ResponseField>

<ResponseField name="expires_in" type="integer" required>
  Lifetime in seconds for the access token.
</ResponseField>

<ResponseField name="scope" type="string" required>
  Space-separated scopes granted to the token.
</ResponseField>

<ResponseField name="refresh_token" type="string">
  Returned for the `authorization_code` grant (unless disabled on the app). Refresh tokens **rotate**: each refresh revokes the one you used and returns a new one. The `client_credentials` grant does not issue refresh tokens — just request a new access token. See [Authorize a user (OAuth)](/guides/oauth-authorization-code#step-6-refresh-the-access-token).
</ResponseField>

## Token lifecycle

<Columns cols={3}>
  <Card title="Issue" icon="badge-check" horizontal>
    Use `/oauth/token` for client credentials, authorization code, and refresh token grants.
  </Card>

  <Card title="Inspect" icon="search-check" horizontal>
    Use `/oauth/introspect` to check token activity and metadata.
  </Card>

  <Card title="Revoke" icon="ban" horizontal>
    Use `/oauth/revoke` to remove access immediately.
  </Card>
</Columns>

## Common failures

<AccordionGroup>
  <Accordion title="401 from OAuth token endpoints" icon="circle-alert">
    Check that the request uses HTTP Basic auth with the client ID and client secret. Also verify that the application secret has not been rotated.
  </Accordion>

  <Accordion title="403 from v2 endpoints" icon="shield-alert">
    The credential is valid, but the application or token does not include a scope accepted by that endpoint. Check the endpoint reference and update the application scope set.
  </Accordion>

  <Accordion title="invalid_scope from /oauth/token" icon="list-x">
    Request only scopes that are enabled on the developer application. Use a space-separated scope string, not commas.
  </Accordion>
</AccordionGroup>

## FAQ

<AccordionGroup>
  <Accordion title="Which method should I use first?" icon="route">
    Start with Basic auth for server-to-server integrations. Move to bearer tokens when your system needs OAuth grant handling or short-lived access tokens.
  </Accordion>

  <Accordion title="Can I use client secrets in frontend code?" icon="lock-keyhole">
    No. Client secrets must stay in trusted server environments.
  </Accordion>

  <Accordion title="Where are scope requirements listed?" icon="list-checks">
    Every endpoint in the API reference declares its required scope. The scopes guide lists the full starter set.
  </Accordion>
</AccordionGroup>
