Skip to content

API keys

An API key is the long-lived server credential for runtime calls such as sdkStart. Create one named key per consumer (an environment, an application) so you can revoke one without breaking the others. Managing keys takes a dashboard JWT. Keys belong to one environment: a sandbox key does not work in production.

Every operation is a POST of { "query", "variables" } to https://api.wetel.dev/graphql (sandbox) with the x-huat-platform: customer header and the credential shown. New here? Start with the Quickstart and the Authentication cheat sheet. Errors are listed in Errors; Postman and OpenAPI files are on Downloads.

OperationKindCredentialWhat it does
createNamedApiKeymutationDashboard JWTCreate a named API key. The raw key is returned once and cannot be read again.
namedApiKeysqueryDashboard JWTList the workspace’s named API keys (metadata only, never the key itself).
revokeNamedApiKeymutationDashboard JWTRevoke one named API key. Immediate and permanent; other keys are not affected.

Create a named API key. The raw key is returned once and cannot be read again.

  • Kind: mutation
  • Credential: Dashboard JWT: Authorization: Bearer <jwt>, from login (a person or a one-off script)
  • Available in: sandbox and production
  • Store key immediately in your server’s secret store. Only a SHA-256 hash is kept on the platform side.
  • Keep id; it is what revokeNamedApiKey takes.
  • scopes is optional and adds rights beyond runtime access. The only accepted value today is templates:hire, and only a workspace owner may grant a scope. Omit it for a plain runtime key.

Request

mutation CreateKey($name: String!, $scopes: [String!]) {
createNamedApiKey(name: $name, scopes: $scopes) {
id
name
key
warning
}
}
variables
{
"name": "helpdesk-sandbox"
}

Code samples

createNamedApiKey.sh
#!/usr/bin/env bash
# createNamedApiKey: Create a named API key. The raw key is returned once and cannot be read again.
# Credential: Dashboard JWT (WETEL_JWT).
API_URL="${WETEL_API_URL:-https://api.wetel.dev/graphql}"
curl -sS "$API_URL" \
-H "Content-Type: application/json" \
-H "x-huat-platform: customer" \
-H "Authorization: Bearer $WETEL_JWT" \
--data-binary @- <<'JSON'
{
"query": "mutation CreateKey($name:String!$scopes:[String!]){createNamedApiKey(name:$name scopes:$scopes){id name key warning}}",
"variables": {
"name": "helpdesk-sandbox"
}
}
JSON

Responses

Success (HTTP 200)

{
"data": {
"createNamedApiKey": {
"id": 31,
"name": "helpdesk-sandbox",
"key": "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"warning": "Save this key immediately. It will not be shown again. Revoking it does not affect any other named key or the legacy tenant API key."
}
}
}
BAD_REQUEST: Unknown scope (sent with scopes [“admin”]) (HTTP 200)
{
"errors": [
{
"message": "Unknown API key scope(s): admin. Allowed: templates:hire.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"createNamedApiKey"
],
"extensions": {
"code": "BAD_REQUEST",
"originalError": {
"message": "Unknown API key scope(s): admin. Allowed: templates:hire.",
"error": "Bad Request",
"statusCode": 400
}
}
}
],
"data": null
}
FORBIDDEN: A member (not the owner) asked for a scope (HTTP 200)
{
"errors": [
{
"message": "Only the owner of this workspace can do this",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"createNamedApiKey"
],
"extensions": {
"code": "FORBIDDEN",
"originalError": {
"message": "Only the owner of this workspace can do this",
"error": "Forbidden",
"statusCode": 403
}
}
}
],
"data": null
}
UNAUTHENTICATED: Called with an API key instead of a JWT (HTTP 200)
{
"errors": [
{
"message": "Unauthorized",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"createNamedApiKey"
],
"extensions": {
"code": "UNAUTHENTICATED",
"originalError": {
"message": "Unauthorized",
"statusCode": 401
}
}
}
],
"data": null
}

List the workspace’s named API keys (metadata only, never the key itself).

  • Kind: query
  • Credential: Dashboard JWT: Authorization: Bearer <jwt>, from login (a person or a one-off script)
  • Available in: sandbox and production
  • Revoked and expired keys are included; filter on revokedAt and expiresAt for an “active only” view.

Request

query ListKeys {
namedApiKeys {
id
name
scopes
createdAt
revokedAt
expiresAt
}
}
variables
{}

Code samples

namedApiKeys.sh
#!/usr/bin/env bash
# namedApiKeys: List the workspace's named API keys (metadata only, never the key itself).
# Credential: Dashboard JWT (WETEL_JWT).
API_URL="${WETEL_API_URL:-https://api.wetel.dev/graphql}"
curl -sS "$API_URL" \
-H "Content-Type: application/json" \
-H "x-huat-platform: customer" \
-H "Authorization: Bearer $WETEL_JWT" \
--data-binary @- <<'JSON'
{
"query": "query ListKeys{namedApiKeys{id name scopes createdAt revokedAt expiresAt}}",
"variables": {}
}
JSON

Responses

Success (HTTP 200)

{
"data": {
"namedApiKeys": [
{
"id": 31,
"name": "helpdesk-sandbox",
"scopes": null,
"createdAt": "2026-10-12T02:40:11.000Z",
"revokedAt": null,
"expiresAt": null
},
{
"id": 24,
"name": "old-test-key",
"scopes": null,
"createdAt": "2026-09-02T08:12:45.000Z",
"revokedAt": "2026-09-30T10:01:02.000Z",
"expiresAt": null
}
]
}
}
UNAUTHENTICATED: Missing credential (HTTP 200)
{
"errors": [
{
"message": "Unauthorized",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"namedApiKeys"
],
"extensions": {
"code": "UNAUTHENTICATED",
"originalError": {
"message": "Unauthorized",
"statusCode": 401
}
}
}
],
"data": null
}

Revoke one named API key. Immediate and permanent; other keys are not affected.

  • Kind: mutation
  • Credential: Dashboard JWT: Authorization: Bearer <jwt>, from login (a person or a one-off script)
  • Available in: sandbox and production
  • There is no un-revoke. Create a new key instead.

Request

mutation RevokeKey($id: Int!) {
revokeNamedApiKey(id: $id)
}
variables
{
"id": 31
}

Code samples

revokeNamedApiKey.sh
#!/usr/bin/env bash
# revokeNamedApiKey: Revoke one named API key. Immediate and permanent; other keys are not affected.
# Credential: Dashboard JWT (WETEL_JWT).
API_URL="${WETEL_API_URL:-https://api.wetel.dev/graphql}"
curl -sS "$API_URL" \
-H "Content-Type: application/json" \
-H "x-huat-platform: customer" \
-H "Authorization: Bearer $WETEL_JWT" \
--data-binary @- <<'JSON'
{
"query": "mutation RevokeKey($id:Int!){revokeNamedApiKey(id:$id)}",
"variables": {
"id": 31
}
}
JSON

Responses

Success (HTTP 200)

{
"data": {
"revokeNamedApiKey": true
}
}
NOT_FOUND: Not a key of your workspace (HTTP 200)
{
"errors": [
{
"message": "Named API key #31 not found",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"revokeNamedApiKey"
],
"extensions": {
"code": "NOT_FOUND",
"status": 404,
"originalError": {
"message": "Named API key #31 not found",
"error": "Not Found",
"statusCode": 404
}
}
}
],
"data": null
}
BAD_USER_INPUT: Id sent as a string (HTTP 400)

Sent with variables:

{
"id": "thirty-one"
}
{
"errors": [
{
"message": "Variable \"$id\" got invalid value \"thirty-one\"; Int cannot represent non-integer value: \"thirty-one\"",
"locations": [
{
"line": 1,
"column": 20
}
],
"extensions": {
"code": "BAD_USER_INPUT"
}
}
]
}