Create MCP API Key
Method
REST method is adopted.
HTTP Method
POST: Create MCP API key
Naming Convention
To unify the naming of query parameters and nodes and improve readability, snake_case is used for URIs and JSON nodes in requests.
Request and Response
Headers
Meta information is set in HTTP headers, not in the response body.
Request Headers
AuthorizationContent-TypeAcceptAccept-language
Response Headers
Content-Type
Create MCP API Key
URI
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| organization_id | integer | Required | Organization ID |
| project_id | integer | Required | Project ID |
Request Body
The request body is JSON.
{
"scope": "project",
"name": "mcp for project A",
"keyPrefix": "abc123",
"permission": 0,
"expiresAt": 1735689600000
}
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| scope | string | Required | API key scope (user or project) |
| name | string | Required | API key name (max 255 characters) |
| keyPrefix | string | Required | Key prefix (max 100 characters, unique) |
| permission | integer | Optional | Access permission (0: READ, 1: WRITE, default: 0) |
| expiresAt | integer | Optional | Expiry timestamp (epoch milliseconds, defaults to creation date + 30 days) |
Response
The response is JSON (HTTP status: 201 Created).
{
"id": 1,
"userId": 1,
"projectId": 2,
"name": "mcp for project A",
"keyPrefix": "abc123",
"apiKey": "guinness_abc123_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"permission": 0,
"expiresAt": 1735689600000,
"revokedAt": null,
"lastUsedAt": null,
"createdAt": 1234567890000,
"updatedAt": 1234567890000,
"deletedAt": null,
"createdBy": "user-cognito-sub",
"updatedBy": "user-cognito-sub",
"deletedBy": null
}
Important: The apiKey is only returned once at creation time. It will not be returned in subsequent requests.
Authentication
Authentication is performed using JSON Web Tokens (JWT) issued by Amazon Cognito.
Error Handling
The status codes for error handling are as follows.
| Description | Status Code | Status Name |
|---|---|---|
| Invalid request (invalid scope, empty name, etc.) | 400 | Bad Request |
| Missing credentials | 401 | Unauthorized |
| Insufficient permissions | 403 | Forbidden |
| Organization or project not found | 404 | Not Found |
| keyPrefix already in use | 409 | Conflict |
| Internal server error | 500 | Internal Server Error |
Processing Flow
- Extract organization ID and project ID from path parameters
- Extract each field from the request body
- Set userId or projectId depending on the scope
- Validate that keyPrefix is unique
- Verify the user or project access permissions
- If expiresAt is not specified, set to creation date + 30 days
- Generate a random salt value and secrets
- Generate the API key (format:
guinness_{keyPrefix}_{secrets}) - Hash the key and save to the database
- Return the created API key information (actual key is only returned at this time)
API Key Structure
API keys are generated in the following format:
Example: guinness_abc123_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Security
- API keys are stored as hashes (
key_hashandsalt) - The actual API key is only returned in the creation response
keyPrefixmust be unique
Detailed Flowchart
flowchart TD
Start([POST Request]) --> Auth[Auth & Parameter Extraction]
Auth --> Service[Service Layer]
Service --> AccessCheck[Access Check]
AccessCheck --> HasAccess{Write permission?}
HasAccess -->|No| Err404[404 Not Found]
HasAccess -->|Yes| Validate[Input Validation]
Validate --> ValidScope{scope validation}
ValidScope -->|NG| Err400[400 Bad Request]
ValidScope -->|OK| CheckPrefix[Check keyPrefix uniqueness]
CheckPrefix --> Duplicate{Duplicate?}
Duplicate -->|Yes| Err409[409 Conflict]
Duplicate -->|No| CreateDB[DB Create<br/>Generate API key]
CreateDB --> Success[201 Created]