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

# Authentication

> Authenticate with the ApartmentIQ API using OAuth client credentials or a Bearer token.

The ApartmentIQ API uses Bearer token authentication. All requests include a token in the `Authorization` header:

```txt theme={null}
Authorization: Bearer <access_token>
```

There are two ways to obtain a token: **API Keys** (recommended for production) and **Access Tokens** (for quick testing).

<Tabs>
  <Tab title="API Keys (recommended)">
    Each API key provides a client ID and secret. Your app exchanges these for short-lived access tokens automatically — no manual token rotation needed.

    ### Create an API Key

    1. In the [web app](https://app.apartmentiq.io), open your user menu (bottom-left avatar) and choose **My Settings**.
    2. In the **API Credentials** section, select the **API Keys** tab.
    3. Click **Create API Key** and give it a name.
    4. Copy both the **Client ID** and **Client Secret**. The secret is only shown once.

    <Warning>Store your client secret securely (e.g., environment variable or secrets manager). It cannot be retrieved after creation.</Warning>

    ### Exchange credentials for an access token

    ```bash theme={null}
    curl -s -X POST https://data.apartmentiq.io/oauth/token \
      -d "grant_type=client_credentials" \
      -d "client_id=<your_client_id>" \
      -d "client_secret=<your_client_secret>"
    ```

    <Tip>You can also send the request body as `application/json` instead of form-encoded parameters.</Tip>

    The response includes an access token and its expiration:

    ```json theme={null}
    {
      "access_token": "sbJACKMpBpOWSZSlHohNmUCO8qergQExotQmCQB_aTo",
      "token_type": "Bearer",
      "expires_in": 7200,
      "scope": "api",
      "created_at": 1746655415
    }
    ```

    ### Make API requests

    Use the access token in the `Authorization` header:

    ```bash theme={null}
    curl -s \
      -H "Authorization: Bearer <access_token>" \
      "https://data.apartmentiq.io/apartmentiq/api/v1/accounts"
    ```

    When the token expires, request a new one using the same client credentials. Most OAuth libraries handle this automatically.

    <Note>Access tokens expire after **2 hours** (`expires_in: 7200`). The libraries below handle token refresh transparently, so you won't need to re-fetch manually.</Note>

    ### SDK quick start

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const CLIENT_ID = process.env.AIQ_CLIENT_ID;
      const CLIENT_SECRET = process.env.AIQ_CLIENT_SECRET;
      const TOKEN_URL = "https://data.apartmentiq.io/oauth/token";
      const BASE_URL = "https://data.apartmentiq.io/apartmentiq/api/v1";

      let token = null;
      let tokenExpiresAt = 0;

      async function getToken() {
        if (token && Date.now() < tokenExpiresAt) return token;
        const res = await fetch(TOKEN_URL, {
          method: "POST",
          headers: { "Content-Type": "application/x-www-form-urlencoded" },
          body: new URLSearchParams({
            grant_type: "client_credentials",
            client_id: CLIENT_ID,
            client_secret: CLIENT_SECRET,
          }),
        });
        if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
        const data = await res.json();
        token = data.access_token;
        tokenExpiresAt = Date.now() + (data.expires_in - 60) * 1000;
        return token;
      }

      // Make an API request
      const res = await fetch(
        `${BASE_URL}/accounts`,
        { headers: { Authorization: `Bearer ${await getToken()}` } }
      );
      console.log(await res.json());
      ```

      ```ruby Ruby theme={null}
      require "oauth2"

      client_id     = ENV.fetch("AIQ_CLIENT_ID")
      client_secret = ENV.fetch("AIQ_CLIENT_SECRET")
      token_url     = "https://data.apartmentiq.io"
      base_url      = "https://data.apartmentiq.io/apartmentiq/api/v1"

      client = OAuth2::Client.new(
        client_id,
        client_secret,
        site: token_url,
        token_url: "oauth/token",
      )

      # Fetch a token using client_credentials grant
      token = client.client_credentials.get_token

      # Make an API request (call token.refresh! when it expires)
      response = token.get("#{base_url}/accounts")
      pp response.parsed
      ```

      ```python Python theme={null}
      import os
      import sys
      import time
      import requests

      CLIENT_ID = os.environ.get("AIQ_CLIENT_ID")
      CLIENT_SECRET = os.environ.get("AIQ_CLIENT_SECRET")
      TOKEN_URL = "https://data.apartmentiq.io/oauth/token"
      BASE_URL = "https://data.apartmentiq.io/apartmentiq/api/v1"

      if not CLIENT_ID or not CLIENT_SECRET:
          sys.exit(
              "Missing credentials. Set the AIQ_CLIENT_ID and "
              "AIQ_CLIENT_SECRET environment variables before running."
          )

      session = requests.Session()
      session.headers.update({"User-Agent": "apartmentiq-api-client/1.0"})

      token = None
      token_expires_at = 0

      def get_token():
          global token, token_expires_at
          if token and time.time() < token_expires_at:
              return token
          res = session.post(TOKEN_URL, data={
              "grant_type": "client_credentials",
              "client_id": CLIENT_ID,
              "client_secret": CLIENT_SECRET,
          })
          res.raise_for_status()
          data = res.json()
          token = data["access_token"]
          token_expires_at = time.time() + (data["expires_in"] - 60)
          return token

      # Make an API request
      res = session.get(
          f"{BASE_URL}/accounts",
          headers={"Authorization": f"Bearer {get_token()}"},
      )
      print(res.json())
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Access Tokens">
    Access tokens are manually generated Bearer tokens. They're useful for quick testing, scripts, and one-off requests.

    <Note>Access tokens expire after 30 days. For production integrations, use an API Key instead.</Note>

    ### Create an access token

    1. In the [web app](https://app.apartmentiq.io), open your user menu (bottom-left avatar) and choose **My Settings**.
    2. In the **API Credentials** section, select the **Access Tokens** tab.
    3. Click **Create Token**, then copy the token shown. It is only displayed once.

    <Warning>Never share your token publicly or commit it to version control.</Warning>

    ### Make API requests

    ```bash theme={null}
    curl -s \
      -H "Authorization: Bearer <your_api_token>" \
      "https://data.apartmentiq.io/apartmentiq/api/v1/accounts"
    ```
  </Tab>
</Tabs>

### Unauthorized responses

You'll receive `401 Unauthorized` if the token is missing, invalid, or expired.

```json theme={null}
{
  "error": "Unauthorized",
  "message": "Missing or invalid bearer token"
}
```
