Skip to content

Your API key

Create one in the portal under API keys.

Browse the API

API reference

API keys

Manage the keys themselves: create, limit, rotate and revoke.

7 endpoints

GET/api/v1/keys

List keys

Every key in the organisation. Revoked keys are included so the history is complete.

keys:read

This endpoint takes no parameters beyond the URL itself.

Example response

json
{
  "keys": [
    {
      "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
      "name": "Autumn rollout",
      "prefix": "sgn_8Kd2mQp1...",
      "scopes": [
        "users:read",
        "users:write"
      ],
      "full_access": false,
      "status": "active",
      "expires_at": null,
      "last_used_at": "2026-09-25T09:41:02.000Z",
      "request_count": 1284
    }
  ],
  "total": 1
}

Copy and paste

curl -X GET "https://api.usesigned.co.uk/api/v1/keys" \
  -H "X-API-Key: $SIGNED_API_KEY"
POST/api/v1/keys

Create a key

Creates an API key. The plaintext key is returned once, in this response, and can never be read back.

keys:write

Parameters

JSON body

  • nameRequired

    stringWhat the key is for. Shown in the audit log.

    up to 100 characters

    example: "Autumn rollout"

  • descriptionOptional

    stringMore detail about who holds it.

    up to 500 characters

  • scopesRequired

    listWhat the key may do. Use ["*"] for full access.

    example: ["users:read","users:write"]

  • rate_limit_per_minuteOptional

    numberRequests a minute. Null means unlimited.

    min 1 · max 100000

  • rate_limit_per_dayOptional

    numberRequests a day. Null means unlimited.

    min 1 · max 10000000

  • allowed_ipsOptional

    listIP addresses the key may be used from. A trailing star matches a range, for example 203.0.113.*. Empty means any address.

  • expires_atOptional

    dateWhen the key stops working, as an ISO date or date and time.

    YYYY-MM-DD

Example request body

json
{
  "name": "Autumn rollout",
  "description": "Nightly sync from the HR system",
  "scopes": [
    "users:read",
    "users:write"
  ],
  "rate_limit_per_minute": 120,
  "allowed_ips": [
    "203.0.113.*"
  ],
  "expires_at": "2027-01-01"
}

Example response

json
{
  "key": {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
    "name": "Autumn rollout",
    "prefix": "sgn_8Kd2mQp1...",
    "scopes": [
      "users:read",
      "users:write"
    ],
    "status": "active"
  },
  "secret": "sgn_8Kd2mQp1xLb4nRt7vHc3yWf6sJm9aQe2Zd5Uk8Xo1pVg"
}

Copy and paste

curl -X POST "https://api.usesigned.co.uk/api/v1/keys" \
  -H "X-API-Key: $SIGNED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Autumn rollout","description": "Nightly sync from the HR system","scopes": ["users:read","users:write"],"rate_limit_per_minute": 120,"allowed_ips": ["203.0.113.*"],"expires_at": "2027-01-01"}'

Worth knowing

Copy the secret now. Only a hash is stored, so it cannot be shown again. If it is lost, rotate the key.

GET/api/v1/keys/{id}

Get a key

Returns one key, without the secret.

keys:read

Parameters

In the path

  • idRequired

    stringAPI key ID.

    uuid

Example response

json
{
  "key": {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
    "name": "Autumn rollout",
    "prefix": "sgn_8Kd2mQp1...",
    "scopes": [
      "users:read",
      "users:write"
    ],
    "status": "active"
  }
}

Copy and paste

curl -X GET "https://api.usesigned.co.uk/api/v1/keys/{id}" \
  -H "X-API-Key: $SIGNED_API_KEY"
PATCH/api/v1/keys/{id}

Update a key

Renames a key, narrows or widens its scopes, changes its rate limits or IP allow-list, or brings its expiry forward. The key itself does not change.

keys:write

Parameters

In the path

  • idRequired

    stringAPI key ID.

    uuid

JSON body

  • nameOptional

    stringWhat the key is for.

    up to 100 characters

  • descriptionOptional

    stringMore detail about who holds it.

    up to 500 characters

  • scopesOptional

    listWhat the key may do. Use ["*"] for full access.

  • rate_limit_per_minuteOptional

    numberRequests a minute. Null means unlimited.

    min 1 · max 100000

  • rate_limit_per_dayOptional

    numberRequests a day. Null means unlimited.

    min 1 · max 10000000

  • allowed_ipsOptional

    listIP addresses the key may be used from. Empty means any address.

  • expires_atOptional

    dateWhen the key stops working, as an ISO date or date and time.

    YYYY-MM-DD

Example request body

json
{
  "scopes": [
    "users:read"
  ],
  "rate_limit_per_minute": 60
}

Example response

json
{
  "key": {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
    "scopes": [
      "users:read"
    ],
    "rate_limit_per_minute": 60
  }
}

Copy and paste

curl -X PATCH "https://api.usesigned.co.uk/api/v1/keys/{id}" \
  -H "X-API-Key: $SIGNED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scopes": ["users:read"],"rate_limit_per_minute": 60}'

Worth knowing

A key cannot widen its own scopes beyond the scopes it already holds, so a limited key cannot promote itself.

DELETE/api/v1/keys/{id}

Revoke a key

Revokes a key immediately. The record is kept so the audit history still makes sense.

keys:write

Parameters

In the path

  • idRequired

    stringAPI key ID.

    uuid

Example response

json
{
  "key": {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
    "status": "revoked",
    "revoked_at": "2026-09-25T10:02:00.000Z"
  }
}

Copy and paste

curl -X DELETE "https://api.usesigned.co.uk/api/v1/keys/{id}" \
  -H "X-API-Key: $SIGNED_API_KEY"

Worth knowing

Revoking the key you are using with this request works, and the response still comes back.

POST/api/v1/keys/{id}/rotate

Rotate a key

Issues a new secret for an existing key and invalidates the old one straight away. Scopes, limits and the name are kept.

keys:write

Parameters

In the path

  • idRequired

    stringAPI key ID.

    uuid

Example response

json
{
  "key": {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b90",
    "prefix": "sgn_3Qw9rTz5..."
  },
  "secret": "sgn_3Qw9rTz5nBv8cKm2xYd7hPf4jSq6aWe1Zu9Lg0Rt"
}

Copy and paste

curl -X POST "https://api.usesigned.co.uk/api/v1/keys/{id}/rotate" \
  -H "X-API-Key: $SIGNED_API_KEY"

Worth knowing

The old secret stops working as soon as this returns, so update the caller before you rotate.

GET/api/v1/keys/{id}/usage

Get key usage

The most recent requests made with this key, and a count per day for the last 30 days.

keys:read

Parameters

In the path

  • idRequired

    stringAPI key ID.

    uuid

Query string

  • pageOptional

    numberPage number, starting at 1.

    default 1 · min 1

  • limitOptional

    numberEntries per page.

    default 50 · min 1 · max 200

Example response

json
{
  "daily": [
    {
      "day": "2026-09-25",
      "requests": 214
    }
  ],
  "requests": [
    {
      "method": "GET",
      "path": "/api/v1/users?limit=50",
      "status": 200,
      "duration_ms": 34,
      "ip": "203.0.113.24",
      "created_at": "2026-09-25T09:41:02.000Z"
    }
  ],
  "total": 1284,
  "page": 1,
  "limit": 50
}

Copy and paste

curl -X GET "https://api.usesigned.co.uk/api/v1/keys/{id}/usage" \
  -H "X-API-Key: $SIGNED_API_KEY"