API keys

Private keys: list, create (secret shown once), revoke.

This is not the live API. This page documents an earlier, in-browser mock API (routes like /accounts, /messaging and /brand), kept for reference. The real, read-only API that runs today is described in The API.

API keys — workspace secrets

Private keys authenticate your programs as your workspace. Each key is scoped (account + groups + send/receive bits) and only its prefix is stored — the full secret appears once at creation. The dashboard's API tab creates and revokes these; this section documents the exact mock these routes are exercised against.

Use GET /api-keys to list, POST /api-keys to create (validates unique name case-insensitively and well-formed scopes), and DELETE /api-keys/{id} to revoke immediately (unknown ids are a no-op 200). All three live in apps/web/src/lib/api/server.ts and are the only routes currently tested by api-coverage.test.ts.

GET /api-keys — List API keys

Records carry the prefix only — there is no secret field to leak.

POST /api-keys — Create an API key

The full secret appears exactly once, in this response.

DELETE /api-keys/{id} — Revoke an API key

Revoking is immediate; unknown ids are a no-op returning the list.

List API keys

Records carry the prefix only — there is no secret field to leak.

GET/api-keys

Response Body

Key list.

TypeScript Definitions

Use the response body type in TypeScript.

apiKeysRequiredarray<object>
curl -X GET "http://localhost:5174/api-keys"
fetch("http://localhost:5174/api-keys")
package mainimport (  "fmt"  "net/http"  "io/ioutil")func main() {  url := "http://localhost:5174/api-keys"  req, _ := http.NewRequest("GET", url, nil)    res, _ := http.DefaultClient.Do(req)  defer res.Body.Close()  body, _ := ioutil.ReadAll(res.Body)  fmt.Println(res)  fmt.Println(string(body))}
import requestsurl = "http://localhost:5174/api-keys"response = requests.request("GET", url)print(response.text)
{
  "apiKeys": [
    {
      "id": "string",
      "name": "string",
      "prefix": "string",
      "secretHash": "string",
      "scopes": {
        "accountId": "string",
        "groupIds": [
          "string"
        ],
        "canSendMessages": true,
        "canReceiveMessages": true
      },
      "createdAt": "string",
      "lastUsedAt": "string"
    }
  ]
}

Create an API key

The full secret appears exactly once, in this response.

POST/api-keys

Request Body

application/jsonRequired
nameRequiredstring

Key name; unique case-insensitively.

scopesRequiredobject

Response Body

Created; key is the full secret (once-only).

TypeScript Definitions

Use the response body type in TypeScript.

apiKeyRequiredobject
apiKeysRequiredarray<object>
keyRequiredstring

Full secret — returned exactly once, never again.

Failure envelope returned with 4xx statuses.

TypeScript Definitions

Use the response body type in TypeScript.

errorRequiredstring

Human-readable failure reason, e.g. "A key needs a name".

Failure envelope returned with 4xx statuses.

TypeScript Definitions

Use the response body type in TypeScript.

errorRequiredstring

Human-readable failure reason, e.g. "A key needs a name".

curl -X POST "http://localhost:5174/api-keys" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "scopes": {      "accountId": "string",      "groupIds": [        "string"      ],      "canSendMessages": true,      "canReceiveMessages": true    }  }'
const body = JSON.stringify({  "name": "string",  "scopes": {    "accountId": "string",    "groupIds": [      "string"    ],    "canSendMessages": true,    "canReceiveMessages": true  }})fetch("http://localhost:5174/api-keys", {  body})
package mainimport (  "fmt"  "net/http"  "io/ioutil"  "strings")func main() {  url := "http://localhost:5174/api-keys"  body := strings.NewReader(`{    "name": "string",    "scopes": {      "accountId": "string",      "groupIds": [        "string"      ],      "canSendMessages": true,      "canReceiveMessages": true    }  }`)  req, _ := http.NewRequest("POST", url, body)  req.Header.Add("Content-Type", "application/json")  res, _ := http.DefaultClient.Do(req)  defer res.Body.Close()  body, _ := ioutil.ReadAll(res.Body)  fmt.Println(res)  fmt.Println(string(body))}
import requestsurl = "http://localhost:5174/api-keys"body = {  "name": "string",  "scopes": {    "accountId": "string",    "groupIds": [      "string"    ],    "canSendMessages": true,    "canReceiveMessages": true  }}response = requests.request("POST", url, json = body, headers = {  "Content-Type": "application/json"})print(response.text)
{
  "apiKey": {
    "id": "string",
    "name": "string",
    "prefix": "string",
    "secretHash": "string",
    "scopes": {
      "accountId": "string",
      "groupIds": [
        "string"
      ],
      "canSendMessages": true,
      "canReceiveMessages": true
    },
    "createdAt": "string",
    "lastUsedAt": "string"
  },
  "apiKeys": [
    {
      "id": "string",
      "name": "string",
      "prefix": "string",
      "secretHash": "string",
      "scopes": {
        "accountId": "string",
        "groupIds": [
          "string"
        ],
        "canSendMessages": true,
        "canReceiveMessages": true
      },
      "createdAt": "string",
      "lastUsedAt": "string"
    }
  ],
  "key": "string"
}
{
  "error": "string"
}
{
  "error": "string"
}

Revoke an API key

Revoking is immediate; unknown ids are a no-op returning the list.

DELETE/api-keys/{id}

Path Parameters

idRequiredstring

Key id.

Response Body

Remaining key list.

TypeScript Definitions

Use the response body type in TypeScript.

apiKeysRequiredarray<object>
curl -X DELETE "http://localhost:5174/api-keys/string"
fetch("http://localhost:5174/api-keys/string")
package mainimport (  "fmt"  "net/http"  "io/ioutil")func main() {  url := "http://localhost:5174/api-keys/string"  req, _ := http.NewRequest("DELETE", url, nil)    res, _ := http.DefaultClient.Do(req)  defer res.Body.Close()  body, _ := ioutil.ReadAll(res.Body)  fmt.Println(res)  fmt.Println(string(body))}
import requestsurl = "http://localhost:5174/api-keys/string"response = requests.request("DELETE", url)print(response.text)
{
  "apiKeys": [
    {
      "id": "string",
      "name": "string",
      "prefix": "string",
      "secretHash": "string",
      "scopes": {
        "accountId": "string",
        "groupIds": [
          "string"
        ],
        "canSendMessages": true,
        "canReceiveMessages": true
      },
      "createdAt": "string",
      "lastUsedAt": "string"
    }
  ]
}