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

# API keys

> Generate, manage, and rotate API keys to authenticate REST API requests.

API keys authenticate your REST requests. Keys are issued **per user** and inherit that user's project access. Pass the key in the JSON body alongside your `userId`.

## Generate a key

<Steps>
  <Step title="Sign in to the dashboard">
    Open [dashboard.streampixel.io](https://dashboard.streampixel.io) and sign in.
  </Step>

  <Step title="Open your account menu">
    Click your account name in the top-right corner.
  </Step>

  <Step title="Request the key">
    Click **Request API Key**. The key is sent to your registered email address and shown once in the dashboard.
  </Step>

  <Step title="Copy and store it">
    Save the key in a password manager or secrets store immediately.
  </Step>
</Steps>

<Warning>
  An API key is shown **only once**. If you lose it, you must generate a new one — there is no way to retrieve the original.
</Warning>

## Use a key in a request

Pass it as `apiKey` in the JSON body — never as an `Authorization` header. Every call also needs your [`userId` and `projectId`](/resources/api-reference/finding-your-user-and-project-ids).

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl -X POST https://api.streampixel.io/pixelStripeApi/projects/upload-file \
    -H "Content-Type: application/json" \
    -d '{
      "apiKey": "YOUR_API_KEY",
      "userId": "YOUR_USER_ID",
      "projectId": "YOUR_PROJECT_ID",
      "fileUrl": "https://storage.example.com/build.zip"
    }'
  ```

  ```javascript Node.js theme={"dark"}
  const res = await fetch(
    'https://api.streampixel.io/pixelStripeApi/projects/upload-file',
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        apiKey: process.env.STREAMPIXEL_API_KEY,
        userId: process.env.STREAMPIXEL_USER_ID,
        projectId: process.env.STREAMPIXEL_PROJECT_ID,
        fileUrl: 'https://storage.example.com/build.zip',
      }),
    }
  );
  ```

  ```python Python theme={"dark"}
  import os, requests

  requests.post(
      'https://api.streampixel.io/pixelStripeApi/projects/upload-file',
      json={
          'apiKey': os.environ['STREAMPIXEL_API_KEY'],
          'userId': os.environ['STREAMPIXEL_USER_ID'],
          'projectId': os.environ['STREAMPIXEL_PROJECT_ID'],
          'fileUrl': 'https://storage.example.com/build.zip',
      },
  )
  ```
</CodeGroup>

## Key scope

A key inherits the access of the user it was generated for:

* **Account owner** — the key works on every project in the account.
* **Team member with `FULL` access** — the key works on every project in their access list.
* **Team member with `READONLY` access** — the key only works for read endpoints on projects in their access list.

If a team member is removed from a project, their key immediately stops working on that project.

## Rotate a key

Rotation is one-step: requesting a new key invalidates the previous one.

<Steps>
  <Step title="Generate a new key">
    Click **Request API Key** in your account menu.
  </Step>

  <Step title="Update your integrations">
    Replace the old key everywhere it is used — env vars, CI secrets, deploy configs.
  </Step>

  <Step title="Verify">
    Make a test request. A `401 Unauthorized: Invalid API Key` means an integration still references the old value.
  </Step>
</Steps>

<Warning>
  Generating a new key takes effect immediately. Any service still using the old key will fail with `401` until you update it.
</Warning>

## Security best practices

* **Never commit keys to source control.** Use env vars or a secrets store.
* **Server-side only.** Don't embed in browser bundles, mobile binaries, or anything users can decompile.
* **Rotate on suspected exposure.** Accidentally pushed to GitHub → rotate immediately, then scrub the commit.
* **Limit teammate scope.** Use `READONLY` or per-project access — their keys inherit the restrictions.

## Troubleshooting

| Status | Message                         | Cause                                                        |
| ------ | ------------------------------- | ------------------------------------------------------------ |
| `401`  | `Unauthorized: Invalid API Key` | Key was rotated, mistyped, or belongs to a different account |
| `401`  | `Invalid User`                  | `userId` does not match the key's owner                      |
| `403`  | `Forbidden`                     | Key owner has no access to the requested project             |

## Next steps

<CardGroup cols={2}>
  <Card title="API authentication" icon="lock" href="/resources/api-reference/api-authentication">
    Full reference for the auth model used by every endpoint.
  </Card>

  <Card title="Find your IDs" icon="id-card" href="/resources/api-reference/finding-your-user-and-project-ids">
    Locate `userId` and `projectId` for use in requests.
  </Card>

  <Card title="Team members" icon="users" href="/resources/dashboard/team-members">
    Control who can issue keys and which projects they cover.
  </Card>

  <Card title="Webhooks" icon="bell" href="/resources/api-reference/webhooks">
    Get push notifications instead of polling the API.
  </Card>
</CardGroup>
