> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.clossir.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.clossir.com/_mcp/server.

# Authentication

GETTING STARTED · AUTHENTICATION

Every Clossir API request authenticates with an **org-scoped API key**. Keys are created in the
dashboard or via the API itself, and each key carries a set of permission scopes that limit
what it can access.

## API keys

```bash title="Authenticating a request"
curl -H "Authorization: Bearer sk_live_..." \
     https://api.signum.tech/identity/parties
```

Or with the SDK:

```ts title="SDK authentication"
import { SignumClient } from "@signum-tech/sdk";

const signum = new SignumClient({
  apiKey: "sk_live_...",
});
```

### Key properties

| Property              | Description                                                                                              |
| --------------------- | -------------------------------------------------------------------------------------------------------- |
| **Org-scoped**        | Every key belongs to one organization. All operations through that key are isolated to that org via RLS. |
| **Network mode**      | Keys can optionally be restricted to `testnet` or `mainnet`. If unset, inherits the org's default.       |
| **Permission scopes** | Fine-grained access control — a key can only perform operations its scopes allow.                        |

## Permission scopes

Each API key is granted a subset of the 16 canonical scopes. Scopes follow the pattern
`{resource}:{action}` where action is `read` or `write`.

| Scope                | Description                   |
| -------------------- | ----------------------------- |
| `orgs:read`          | Read organization data        |
| `orgs:write`         | Create/update organizations   |
| `assets:read`        | Read assets                   |
| `assets:write`       | Create/update/delete assets   |
| `members:read`       | Read org members              |
| `members:write`      | Add/remove/update members     |
| `wallets:read`       | Read wallets                  |
| `wallets:write`      | Create/manage wallets         |
| `chains:read`        | Read chain registry           |
| `chains:write`       | Enable/disable chains for org |
| `attestations:read`  | Read attestations             |
| `attestations:write` | Create/revoke attestations    |
| `transfers:read`     | Read transfers                |
| `transfers:write`    | Initiate transfers            |
| `api-keys:read`      | List API keys                 |
| `api-keys:write`     | Create/revoke API keys        |

A `write` scope on a resource does **not** imply `read`. If your integration needs to both
create attestations and query their status, grant both `attestations:write` and
`attestations:read`.

### Recommended scope sets

| Use case             | Scopes                                                                            |
| -------------------- | --------------------------------------------------------------------------------- |
| Read-only dashboard  | `orgs:read`, `assets:read`, `members:read`, `attestations:read`, `transfers:read` |
| Attestation issuer   | `attestations:read`, `attestations:write`, `wallets:read`                         |
| Full platform access | All 16 scopes                                                                     |
| Key management only  | `api-keys:read`, `api-keys:write`                                                 |

## Error handling

The Clossir API returns errors as RFC 9457 `application/problem+json` responses — structured,
machine-readable error bodies with consistent fields.

### Error shape

```json title="Example error response"
{
  "type": "https://api.signum.tech/errors/insufficient-scope",
  "title": "Forbidden",
  "status": 403,
  "detail": "This API key does not have the 'attestations:write' scope required for this operation."
}
```

### Standard fields

| Field      | Type      | Description                                                            |
| ---------- | --------- | ---------------------------------------------------------------------- |
| `type`     | `string`  | URI identifying the error type. `about:blank` for generic HTTP errors. |
| `title`    | `string`  | Short, human-readable summary of the problem.                          |
| `status`   | `number`  | The HTTP status code.                                                  |
| `detail`   | `string`  | Human-readable explanation specific to this occurrence.                |
| `instance` | `string?` | URI identifying the specific request (for support reference).          |

### Common error types

| Status | Type URI                    | When                                                                                           |
| ------ | --------------------------- | ---------------------------------------------------------------------------------------------- |
| `401`  | `about:blank`               | Missing or invalid API key                                                                     |
| `403`  | `.../insufficient-scope`    | Key lacks the required scope for this operation                                                |
| `409`  | `.../prerequisites-not-met` | A prerequisite state is not satisfied (includes `prerequisites[]` array with resolution hints) |
| `422`  | `about:blank`               | Request body validation failed                                                                 |
| `429`  | `about:blank`               | Rate limit exceeded                                                                            |

### Prerequisite errors

Some operations require prior state — for example, creating an attestation requires the party
to exist. When prerequisites are not met, the response includes resolution hints:

```json title="409 Prerequisite failure"
{
  "type": "https://api.signum.tech/errors/prerequisites-not-met",
  "title": "Prerequisites not met",
  "status": 409,
  "detail": "Cannot create attestation: party has not completed identity verification.",
  "prerequisites": [
    {
      "state": "party_verified",
      "satisfied": false,
      "detail": "Party pty_abc123 has not completed KYC.",
      "resolution": {
        "method": "POST",
        "path": "/identity/parties/pty_abc123/verify",
        "description": "Initiate identity verification for this party"
      }
    }
  ],
  "dependencyChain": ["party_exists", "party_verified", "attestation_eligible"]
}
```

The `resolution` field tells you exactly which API call to make to satisfy the prerequisite.

## Next steps

* [Quickstart](/getting-started/quickstart) — see authentication in action
* [API Reference](/api/overview) — explore the full operation catalog
* [Webhooks](/solutions/infra/webhooks) — receive async notifications when state changes