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

# API Quickstart

> Create a service account and API key in the Developer Hub, authenticate with Basic auth, and make your first request to the Living Security Public API.

Create a service account and an API key in the Developer Hub, then make your
first request. This quickstart uses API-key authentication; you do not need an
OAuth client. See [Authentication](/developers/v1/authentication) if your
integration requires short-lived OAuth access tokens.

## Prerequisites

* Admin access to the Living Security Dashboard.
* The Developer Hub visible under **Settings → Integrations & Developers →
  Developer Hub**.

## Create credentials

<Steps>
  <Step title="Create a service account">
    In the Developer Hub, open the **Service accounts** tab and create an
    account. Give it a descriptive name (for example `reporting-pipeline`) and
    grant the permissions its keys may use — for this guide, `organization:read`
    is enough.

    The account's permissions are the ceiling for every key created under it:
    a key can never do more than its service account allows.
  </Step>

  <Step title="Create an API key">
    Open the service account's detail page and create a key. Pick the
    permissions this specific key needs (a subset of the account's) and an
    expiration — 30, 90, or 365 days, or a custom period. Expiration is
    mandatory.

    The key's secret starts with `lsk_live_` and is shown **once**. Copy it
    into a secret manager immediately; it cannot be retrieved later.

    <Warning>
      Never commit API key secrets to version control or embed them in client-side
      code. Anyone holding the secret can act with the key's permissions.
    </Warning>
  </Step>

  <Step title="Choose your region">
    Call the regional `/v1` host that matches the organization's data
    residency. Keys authenticate only on that host.

    | Region | Base URL |
    | - | - |
    | US | `https://api.us-east-1.livingsecurity.ai/v1` |
    | EU | `https://api.eu-west-1.livingsecurity.ai/v1` |

    See [Regions](/developers/v1/regions) if you are not sure which host to
    use. A valid key sent to the other region fails as `unauthorized`. Use
    the region dropdown on the sample below to switch the host.
  </Step>

  <Step title="Make your first request">
    Load `LIVING_SECURITY_API_KEY` from your secret manager into the environment
    of the process making the request. The examples below read it without embedding
    a secret in source code. For Python, install `requests` first.

    Call the API with the secret in the HTTP Basic auth password or username
    field — either works, so clients that require both fields filled (such as
    Power BI's Web connector) can put a placeholder like `apikey` in the other
    field.

    <CodeGroup>
      ```bash cURL theme={null}
      curl --fail-with-body --connect-timeout 5 --max-time 30 \
        https://api.eu-west-1.livingsecurity.ai/v1/organization \
        -u "apikey:${LIVING_SECURITY_API_KEY:?Set LIVING_SECURITY_API_KEY}" \
        -H "Living-Security-Version: 2026-07-01"
      ```

      ```bash cURL (key as username) theme={null}
      curl --fail-with-body --connect-timeout 5 --max-time 30 \
        https://api.eu-west-1.livingsecurity.ai/v1/organization \
        -u "${LIVING_SECURITY_API_KEY:?Set LIVING_SECURITY_API_KEY}:" \
        -H "Living-Security-Version: 2026-07-01"
      ```

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

      BASE = "https://api.eu-west-1.livingsecurity.ai/v1"

      response = requests.get(
          f"{BASE}/organization",
          auth=("apikey", os.environ["LIVING_SECURITY_API_KEY"]),
          headers={"Living-Security-Version": "2026-07-01"},
          timeout=(5, 30),
          allow_redirects=False,
      )
      response.raise_for_status()
      if response.status_code != 200:
          raise RuntimeError("Unexpected response; check your regional API URL")
      print(response.json())
      ```
    </CodeGroup>

    A successful response returns your organization:

    ```json Response theme={null}
    {
      "id": "1e2f3a4b-5c6d-4e7f-8a9b-0c1d2e3f4a5b",
      "object": "organization",
      "name": "Example Corp",
      "region": "eu",
      "plan": "enterprise",
      "subscription_status": "active",
      "created_at": "2024-03-12T18:04:11.000Z"
    }
    ```

    <Check>
      If you get this response, your credentials work. The request also appears in
      the Developer Hub's **Request logs** tab within moments.
    </Check>
  </Step>
</Steps>

<Tip>
  Bearer authentication with the same secret (`Authorization: Bearer
    lsk_live_...`) also works. Basic auth exists so tools that only speak
  username/password — like Power BI's Web connector — can connect.
</Tip>

## How authentication works

* **The credential determines the organization.** `/v1` requests carry no
  tenant selector: no organization path segment and no organization header.
  Sending an `x-organization-id` header is rejected with `invalid_request`.
  The host must still match that organization's region. See
  [Regions](/developers/v1/regions).
* **Permissions are checked per operation.** Each `/v1` operation requires a
  named permission (for example, `GET /v1/organization` requires
  `organization:read`). A key missing the permission gets a `403` with code
  `insufficient_permission`.
* **Keys expire and can be rotated without downtime.** See
  [API keys](/developers/developer-hub/api-keys) for rotation with an overlap
  window.

## Reading error responses

Every `/v1` error is `application/problem+json`
([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)) with a stable machine
code. For example, a request with a missing or unknown credential returns:

```json 401 Unauthorized theme={null}
{
  "type": "https://docs.livingsecurity.com/developers/v1/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "No valid API credential was provided.",
  "code": "unauthorized",
  "request_id": "req_...",
  "doc_url": "https://docs.livingsecurity.com/developers/v1/errors/unauthorized",
  "retryable": false
}
```

Branch on `code`, never on `detail`. Follow `doc_url` for the resolution
steps, and include `request_id` when contacting support — it matches the
`Request-Id` response header and the Developer Hub request logs. The full
code set is in the [error reference](/developers/v1/errors/overview).

## Contract versions

Every response echoes the contract version that served it in the
`Living-Security-Version` header, alongside a `Request-Id` header for
correlation.

You can pin a request to a published contract version by date:

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body --connect-timeout 5 --max-time 30 \
    https://api.eu-west-1.livingsecurity.ai/v1/organization \
    -u "apikey:${LIVING_SECURITY_API_KEY:?Set LIVING_SECURITY_API_KEY}" \
    -H "Living-Security-Version: 2026-07-01"
  ```
</CodeGroup>

The version resolves in this order: the request header if present, otherwise
the service account's pinned default, otherwise the latest published version.
Requesting a version that is not published (or is past its sunset date)
returns a `400` with code `unsupported_version`. Published versions and their
changes are listed in the [API changelog](/developers/v1/changelog).

## Troubleshoot your first request

| Result | Next action |
| - | - |
| `401 unauthorized` | Check the secret, its expiration, and the organization's region. Do not try other hosts with a live credential. |
| `403 insufficient_permission` | Grant `organization:read` to both the service account and its key. |
| `400 unsupported_version` | Choose a published version from the [changelog](/developers/v1/changelog). |
| `429 rate_limited` | Wait for `Retry-After`; follow the [bounded retry example](/developers/v1/rate-limits). |
| Network timeout | Check connectivity and retry this read within your application's retry budget. |

For other errors, follow the response's `doc_url`. Keep the `Request-Id` for
support; never include the Authorization header or your API key in a ticket.

## Next steps

<CardGroup cols={2}>
  <Card title="Regions" href="/developers/v1/regions">
    Choose the US or EU `/v1` host for the organization.
  </Card>

  <Card title="Pagination" href="/developers/v1/pagination">
    Walk lists with `page_token` and the list envelope.
  </Card>

  <Card title="Rate limits" href="/developers/v1/rate-limits">
    Understand request budgets and handle `429` responses.
  </Card>

  <Card title="Error reference" href="/developers/v1/errors/overview">
    Every error code, its HTTP status, and how to resolve it.
  </Card>

  <Card title="Developer Hub" href="/developers/developer-hub/overview">
    Manage service accounts, API keys, and request logs.
  </Card>
</CardGroup>


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