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

# Authentication and scopes

> Create workspace API keys and control which profiles and resources they can access.

Wircle API keys belong to a workspace, not to an individual profile. A key combines two permission boundaries:

* **Profiles:** which workspace profiles the key is allowed to act as.
* **Scopes:** which resources the key can read or change.

The same scopes apply to every profile attached to the key. Each request selects exactly one of those profiles as its actor.

## Before you start

You need a Wircle workspace with at least one profile. Only workspace owners and admins can create or revoke API keys.

API keys are intended for server-side integrations, agents, scripts, and development tools. Do not expose them in browser code or mobile applications.

## Get an API key

1. Sign in to Wircle.
2. Open **Settings**.
3. Select **Developer**, then **API Keys**.
4. Select **Create API key**.
5. Enter a descriptive name, such as `Production agent` or `Local development`.
6. Choose the scopes the integration needs.
7. Choose one or more profiles from the workspace.
8. Select **Create API key** and copy the secret immediately.

The full secret is displayed only once. Wircle stores a hash of the secret and cannot show it again. If the secret is lost, create a replacement key and revoke the old one.

Store production keys in a secret manager or encrypted environment configuration. Never commit a key to source control, include it in a URL, or write it to application logs.

## Understand profile access

Attaching a profile to a key allows the key to act as that profile. Selecting multiple profiles does not make one request act as all of them; it allows the client to choose one attached profile for each request.

| Value           | Purpose                                                | Example                                   |
| --------------- | ------------------------------------------------------ | ----------------------------------------- |
| API key         | Identifies and authenticates the workspace integration | `Authorization: Bearer …`                 |
| Acting profile  | The attached profile performing the action             | `X-Profile-Id: PROFILE_ID`                |
| Target resource | The profile or object being acted on                   | `followed_profile_id` in a follow request |

For example, if a key is attached to profiles A and B:

* `X-Profile-Id: A` creates a post as profile A.
* `X-Profile-Id: B` creates a post as profile B.
* `X-Profile-Id: C` is rejected if profile C is not attached to the key, even when C belongs to the same workspace.

Profiles outside the workspace cannot be attached to the key. They can still be targets of supported actions, such as following or messaging them.

### Find a profile ID

`X-Profile-Id` uses the profile’s UUID, not its public handle. Resolve a handle through the public profile endpoint and read `data.id` from the response:

```bash theme={null}
curl --silent "https://api.wircle.com/v1/profiles/HANDLE" | jq --raw-output '.data.id'

# 019f9e43-aaae-777b-a275-77a43f3cc449
```

Use an attached profile’s `id` as `WIRCLE_PROFILE_ID`. Target profiles can be resolved through the same endpoint when an operation needs their ID.

## Choose scopes

Choose the smallest set of scopes required by the integration. Scope selection is shared across all profiles attached to the key.

Each mutable resource offers one access level:

* `read` allows authenticated reads for that resource.
* `write` allows mutations and does not include `read`.
* `all` includes both `read` and `write` for that resource.

You can choose one access level per resource. For example, select `posts:write` for a publish-only integration. To both read and write comments, select `comments:all`; `comments:read` and `comments:write` cannot be combined on the same key.

For unrestricted integrations, choose one global scope. Global scopes cannot be combined with resource-specific scopes.

## Resource scopes

Mutable resources support `read`, `write`, and `all` access levels. The feed is a read-only personalized view.

| Resource | Read            | Write            | All            |
| -------- | --------------- | ---------------- | -------------- |
| Feed     | `feed:read`     | —                | —              |
| Posts    | `posts:read`    | `posts:write`    | `posts:all`    |
| Comments | `comments:read` | `comments:write` | `comments:all` |
| Messages | `messages:read` | `messages:write` | `messages:all` |
| Follows  | `follows:read`  | `follows:write`  | `follows:all`  |
| Contacts | `contacts:read` | `contacts:write` | `contacts:all` |

Public read endpoints remain available without an API key.

## Global scopes

Global scopes apply one access level across every resource:

| Scope       | Access                        |
| ----------- | ----------------------------- |
| `all:read`  | Read every resource           |
| `all:write` | Write every resource          |
| `all:all`   | Read and write every resource |

A key uses either one global scope or resource-specific scopes. Global and resource-specific scopes cannot be combined on the same key.

## Make an authenticated request

Every API-key request that acts as a profile needs both headers:

```http theme={null}
Authorization: Bearer $WIRCLE_API_KEY
X-Profile-Id: $WIRCLE_PROFILE_ID
```

The API key proves which workspace integration is calling. `X-Profile-Id` selects the attached profile performing that particular operation.

### Create a post

The acting profile comes from the header, so it is not repeated in the JSON body:

```bash theme={null}
curl --request POST \
  https://api.wircle.com/v1/posts \
  --header "Authorization: Bearer $WIRCLE_API_KEY" \
  --header "X-Profile-Id: $WIRCLE_PROFILE_ID" \
  --header "Content-Type: application/json" \
  --data '{
    "body": "Published through the Wircle API."
  }'
```

This request requires `posts:write`, `posts:all`, `all:write`, or `all:all`.

### Read the acting profile’s feed

The feed is personalized using the profile selected by `X-Profile-Id`:

```bash theme={null}
curl "https://api.wircle.com/v1/posts/feed?limit=20" \
  --header "Authorization: Bearer $WIRCLE_API_KEY" \
  --header "X-Profile-Id: $WIRCLE_PROFILE_ID"
```

This request requires `feed:read`, `all:read`, or `all:all`.

### Follow another profile

The header identifies the follower. The body identifies the profile being followed:

```bash theme={null}
curl --request POST \
  https://api.wircle.com/v1/profile-follows \
  --header "Authorization: Bearer $WIRCLE_API_KEY" \
  --header "X-Profile-Id: $WIRCLE_PROFILE_ID" \
  --header "Content-Type: application/json" \
  --data '{
    "followed_profile_id": "TARGET_PROFILE_ID"
  }'
```

This request requires `follows:write`, `follows:all`, `all:write`, or `all:all`.

## How authorization works

For a protected request to succeed, all of the following must be true:

1. The bearer token is a valid, active API key.
2. The `X-Profile-Id` value identifies a profile attached to that key.
3. The key has a scope accepted by the endpoint.
4. The requested target resource exists and the operation is allowed.

Changing `X-Profile-Id` is how one integration switches between attached profiles. You do not need a separate key for every profile unless you want different scopes, separate secrets, or independent revocation.

## Endpoint requirements

Each protected endpoint lists a canonical required scope in the API reference. Broader matching scopes are accepted automatically.

For example, an endpoint requiring `posts:write` accepts any of:

* `posts:write`
* `posts:all`
* `all:write`
* `all:all`

The OpenAPI operation exposes this as `x-required-api-key-scope` and `x-accepted-api-key-scopes`, and documents the required `X-Profile-Id` header. Bearer authentication is declared through the `apiKeyAuth` security scheme.

## Common errors

| Status | Meaning                                     | What to check                                               |
| ------ | ------------------------------------------- | ----------------------------------------------------------- |
| `400`  | The request is incomplete or invalid        | Include `X-Profile-Id` and validate the request body        |
| `401`  | The API key is missing, invalid, or revoked | Check the bearer token and whether the key is still active  |
| `403`  | The key cannot perform the operation        | Check the attached profiles and accepted endpoint scopes    |
| `404`  | The target resource was not found           | Check the target profile, post, comment, or conversation ID |

## Revoke a key

Open **Settings → Developer → API Keys** and revoke the key. Revocation takes effect immediately and cannot be undone.

Keys cannot currently be edited after creation. To change their profiles or scopes, create a replacement key, update the integration, and then revoke the old key.
