# Create an API key

POST /api/keys

**Required scope:** `keys:manage`. **Roles:** Reviewer, Owner, Admin.

Returns the secret once. Save it privately. Non-admins issue only for themselves; Admin may specify an enabled Math member. Role and scopes cannot exceed the issuer or target member. Default expiry 90 days, maximum 365; 50 active keys per member. Defaults inherit issuer role/scopes.

Examples use synthetic data. This is a complete OpenAPI document for this operation, including required schemas.

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Create an API key",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://math-api.qmindlabs.ai",
      "description": "Main Math API"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/api/keys": {
      "post": {
        "tags": [
          "API keys"
        ],
        "summary": "Create an API key",
        "operationId": "post__api_keys",
        "description": "**Required scope:** `keys:manage`. **Roles:** Reviewer, Owner, Admin.\n\nReturns the secret once. Save it privately. Non-admins issue only for themselves; Admin may specify an enabled Math member. Role and scopes cannot exceed the issuer or target member. Default expiry 90 days, maximum 365; 50 active keys per member. Defaults inherit issuer role/scopes.",
        "x-required-scopes": [
          "keys:manage"
        ],
        "parameters": [],
        "responses": {
          "201": {
            "description": "Created successfully",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyCreated"
                },
                "example": {
                  "key": {
                    "id": "bbbbbbbbbbbbbbbbbbbbbbbb",
                    "actor_id": 42,
                    "name": "example",
                    "role": "REVIEWER",
                    "scopes": [
                      "read"
                    ],
                    "workspace_id": "ws_math",
                    "environment": "dev",
                    "created_by": 42,
                    "created_at": "2026-09-22T12:00:00.000Z",
                    "expires_at": "2026-09-22T12:00:00.000Z",
                    "revoked_at": null,
                    "last_used_at": null
                  },
                  "token": "YOUR_NEW_API_KEY",
                  "token_shown_once": true
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_request",
                  "message": "Invalid input"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired or revoked API key",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "invalid_api_key",
                  "message": "Missing, invalid, expired or revoked API key"
                }
              }
            }
          },
          "403": {
            "description": "Role, scope, account or origin does not permit this operation",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "api_key_scope_required",
                  "message": "Role, scope, account or origin does not permit this operation"
                }
              }
            }
          },
          "404": {
            "description": "Resource unavailable or outside your permitted tasks",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "not_found",
                  "message": "Resource unavailable or outside your permitted tasks"
                }
              }
            }
          },
          "405": {
            "description": "HTTP method is not supported",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "method_not_allowed",
                  "message": "HTTP method is not supported"
                }
              }
            }
          },
          "409": {
            "description": "Stale version, invalid workflow transition or changed evidence; read the latest state before retrying",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "math_workflow_conflict",
                  "message": "Stale version, invalid workflow transition or changed evidence; read the latest state before retrying"
                }
              }
            }
          },
          "413": {
            "description": "Request exceeds the permitted upload or JSON size",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "payload_too_large",
                  "message": "Request exceeds the permitted upload or JSON size"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported request Content-Type",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "json_required",
                  "message": "Unsupported request Content-Type"
                }
              }
            }
          },
          "429": {
            "description": "600 authenticated requests per minute per key exceeded; retry next minute",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "api_key_rate_limited",
                  "message": "600 authenticated requests per minute per key exceeded; retry next minute"
                }
              }
            }
          },
          "503": {
            "description": "Service, storage or capacity temporarily unavailable",
            "headers": {
              "x-request-id": {
                "description": "Server-generated identifier for tracing this request.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "service_unavailable",
                  "message": "Service, storage or capacity temporarily unavailable"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeyCreate"
              },
              "examples": {
                "readonly": {
                  "summary": "Read-only automation key",
                  "value": {
                    "name": "Read-only reporting",
                    "scopes": [
                      "read",
                      "files:read",
                      "paths:read"
                    ],
                    "expires_in_days": 90
                  }
                },
                "reviewer": {
                  "summary": "Admin issues a reviewer key",
                  "value": {
                    "name": "Reviewer automation",
                    "actor_id": 42,
                    "role": "REVIEWER",
                    "scopes": [
                      "read",
                      "write",
                      "files:read",
                      "files:write",
                      "paths:read"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Math API key",
        "description": "Paste your issued key, without the Bearer prefix. No key is embedded in this documentation."
      }
    },
    "schemas": {
      "KeyCreated": {
        "type": "object",
        "properties": {
          "key": {
            "$ref": "#/components/schemas/Key"
          },
          "token": {
            "type": "string",
            "example": "YOUR_NEW_API_KEY",
            "description": "Secret returned only on creation. Store privately; it cannot be retrieved again."
          },
          "token_shown_once": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "key",
          "token",
          "token_shown_once"
        ],
        "additionalProperties": false
      },
      "Key": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9a-f]{24}$",
            "example": "bbbbbbbbbbbbbbbbbbbbbbbb"
          },
          "actor_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991,
            "example": 42
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "REVIEWER",
              "OWNER",
              "ADMIN"
            ]
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "files:read",
                "files:write",
                "paths:read",
                "keys:manage"
              ]
            },
            "minItems": 1,
            "maxItems": 6,
            "uniqueItems": true
          },
          "workspace_id": {
            "type": "string",
            "const": "ws_math"
          },
          "environment": {
            "type": "string",
            "const": "dev"
          },
          "created_by": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991,
            "example": 42
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-22T12:00:00.000Z"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-22T12:00:00.000Z"
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "example": "2026-09-22T12:00:00.000Z"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "example": "2026-09-22T12:00:00.000Z"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "actor_id",
          "name",
          "role",
          "scopes",
          "workspace_id",
          "environment",
          "created_by",
          "created_at",
          "expires_at",
          "revoked_at",
          "last_used_at"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "api_key_scope_required"
          },
          "message": {
            "type": "string",
            "example": "This operation requires the read scope."
          }
        },
        "required": [
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "KeyCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "example": "Read-only reporting"
          },
          "role": {
            "type": "string",
            "enum": [
              "REVIEWER",
              "OWNER",
              "ADMIN"
            ],
            "description": "Defaults to the issuer’s effective role. Cannot exceed issuer or target member."
          },
          "actor_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991,
            "example": 42,
            "description": "Defaults to yourself. Only Admin can issue keys for another enabled Math member."
          },
          "expires_in_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 365,
            "default": 90
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "files:read",
                "files:write",
                "paths:read",
                "keys:manage"
              ]
            },
            "minItems": 1,
            "maxItems": 6,
            "uniqueItems": true,
            "description": "Defaults to issuer scopes. Cannot exceed issuer scopes.",
            "example": [
              "read",
              "files:read"
            ]
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      }
    }
  }
}
```
