{
    "openapi": "3.1.0",
    "info": {
        "title": "DailyPlay API",
        "description": "Create and manage one-time game session tokens for third-party integrations with DailyPlay. Requires a Business tier organization.",
        "version": "1.0.0",
        "contact": {
            "name": "DailyPlay Support",
            "url": "https://docs.dailyplay.ai",
            "email": "security@dailyplay.ai"
        }
    },
    "servers": [
        {
            "url": "https://app.dailyplay.ai",
            "description": "Production"
        }
    ],
    "security": [
        {
            "apiKey": []
        }
    ],
    "paths": {
        "/api/org-api-keys?action=create-session": {
            "post": {
                "operationId": "createSession",
                "summary": "Create a one-time session token",
                "description": "Creates a single-use session token that grants one play of a game or stream. The token is passed in the game URL to authorize access.",
                "tags": [
                    "Sessions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateSessionRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Session token created successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreateSessionResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/org-api-keys?action=validate-session&token={token}": {
            "get": {
                "operationId": "validateSession",
                "summary": "Validate a session token",
                "description": "Checks whether a session token is still valid (active and not expired) without consuming it.",
                "tags": [
                    "Sessions"
                ],
                "security": [],
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "description": "The session token UUID to validate",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Token validation result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidateSessionResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    }
                }
            }
        },
        "/api/org-api-keys?action=consume-session": {
            "post": {
                "operationId": "consumeSession",
                "summary": "Consume a session token",
                "description": "Atomically consumes a session token so it cannot be reused. Call this when the user starts playing.",
                "tags": [
                    "Sessions"
                ],
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ConsumeSessionRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Session consumed successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ConsumeSessionResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "410": {
                        "description": "Token already consumed or expired",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/org-api-keys": {
            "get": {
                "operationId": "listApiKeys",
                "summary": "List API keys for an organization",
                "description": "Returns all API keys for the specified organization. Requires Clerk bearer token authentication.",
                "tags": [
                    "API Keys"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "org_id",
                        "in": "query",
                        "required": true,
                        "description": "Organization ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "List of API keys",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/ApiKey"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    }
                }
            },
            "post": {
                "operationId": "createApiKey",
                "summary": "Create a new API key",
                "description": "Creates a new API key for an organization. The raw key is only returned once in the response.",
                "tags": [
                    "API Keys"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateApiKeyRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "API key created. The `key` field is only included in this response.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreateApiKeyResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    }
                }
            },
            "patch": {
                "operationId": "updateApiKey",
                "summary": "Update or revoke an API key",
                "description": "Update API key properties. Set `is_active` to false to revoke, or true to reactivate.",
                "tags": [
                    "API Keys"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "id",
                                    "org_id"
                                ],
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "API key ID"
                                    },
                                    "org_id": {
                                        "type": "integer",
                                        "description": "Organization ID"
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "Set false to revoke, true to reactivate"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "API key updated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SuccessResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    }
                }
            },
            "delete": {
                "operationId": "deleteApiKey",
                "summary": "Permanently delete an API key",
                "description": "Permanently removes the API key record.",
                "tags": [
                    "API Keys"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "required": true,
                        "description": "API key ID",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "org_id",
                        "in": "query",
                        "required": true,
                        "description": "Organization ID",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "API key deleted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SuccessResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "apiKey": {
                "type": "apiKey",
                "in": "header",
                "name": "x-api-key",
                "description": "API key in the format `dpk_<40 hex chars>`. Used for session token operations."
            },
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Clerk JWT bearer token. Used for dashboard/management endpoints."
            }
        },
        "schemas": {
            "CreateSessionRequest": {
                "type": "object",
                "properties": {
                    "game_id": {
                        "type": "integer",
                        "description": "Target game ID. At least one of game_id or stream_id is required.",
                        "example": 42
                    },
                    "stream_id": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Target stream ID. At least one of game_id or stream_id is required."
                    },
                    "external_ref": {
                        "type": "string",
                        "description": "Your tracking reference (e.g. user ID, order ID)",
                        "example": "user-12345"
                    },
                    "metadata": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Arbitrary JSON data for your own tracking",
                        "example": {
                            "campaign": "summer-promo"
                        }
                    },
                    "expires_in_minutes": {
                        "type": "integer",
                        "description": "Token expiry in minutes. Default: 1440 (24 hours)",
                        "default": 1440,
                        "example": 60
                    }
                }
            },
            "CreateSessionResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "token": {
                                "type": "string",
                                "format": "uuid",
                                "description": "The one-time session token",
                                "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                            },
                            "stream_id": {
                                "type": "integer",
                                "nullable": true
                            },
                            "game_id": {
                                "type": "integer",
                                "example": 42
                            },
                            "expires_at": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2026-02-17T12:00:00.000Z"
                            },
                            "external_ref": {
                                "type": "string",
                                "example": "user-12345"
                            }
                        }
                    }
                }
            },
            "ValidateSessionResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "valid": {
                                "type": "boolean"
                            },
                            "status": {
                                "type": "string",
                                "enum": [
                                    "active",
                                    "consumed",
                                    "expired",
                                    "revoked"
                                ]
                            },
                            "stream_id": {
                                "type": "integer",
                                "nullable": true
                            },
                            "game_id": {
                                "type": "integer"
                            },
                            "expires_at": {
                                "type": "string",
                                "format": "date-time"
                            },
                            "external_ref": {
                                "type": "string"
                            },
                            "metadata": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    }
                }
            },
            "ConsumeSessionRequest": {
                "type": "object",
                "required": [
                    "token"
                ],
                "properties": {
                    "token": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The session token to consume",
                        "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                    },
                    "player_uuid": {
                        "type": "string",
                        "description": "UUID identifying the player",
                        "example": "player-uuid-here"
                    }
                }
            },
            "ConsumeSessionResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "session_id": {
                                "type": "integer",
                                "example": 1
                            },
                            "org_id": {
                                "type": "integer",
                                "example": 5
                            },
                            "stream_id": {
                                "type": "integer",
                                "nullable": true
                            },
                            "game_id": {
                                "type": "integer",
                                "example": 42
                            },
                            "external_ref": {
                                "type": "string",
                                "example": "user-12345"
                            },
                            "metadata": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    }
                }
            },
            "CreateApiKeyRequest": {
                "type": "object",
                "required": [
                    "org_id",
                    "name"
                ],
                "properties": {
                    "org_id": {
                        "type": "integer",
                        "description": "Organization ID",
                        "example": 1
                    },
                    "name": {
                        "type": "string",
                        "description": "Descriptive name for the key",
                        "example": "Production CRM"
                    },
                    "description": {
                        "type": "string",
                        "description": "Optional description",
                        "example": "Used by the CRM to issue game links"
                    },
                    "allowed_game_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true,
                        "description": "Restrict key to specific game IDs. Null = all games.",
                        "example": [
                            42,
                            43
                        ]
                    },
                    "allowed_stream_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true,
                        "description": "Restrict key to specific stream IDs. Null = all streams."
                    },
                    "rate_limit_per_minute": {
                        "type": "integer",
                        "description": "Max requests per minute",
                        "default": 60,
                        "example": 60
                    },
                    "rate_limit_per_day": {
                        "type": "integer",
                        "description": "Max requests per day",
                        "default": 10000,
                        "example": 10000
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Optional auto-expiry date",
                        "example": "2027-01-01T00:00:00Z"
                    }
                }
            },
            "CreateApiKeyResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "example": 1
                            },
                            "name": {
                                "type": "string",
                                "example": "Production CRM"
                            },
                            "key_prefix": {
                                "type": "string",
                                "description": "First 8 characters for identification",
                                "example": "dpk_a1b2"
                            },
                            "key": {
                                "type": "string",
                                "description": "The full API key. Only shown once at creation time.",
                                "example": "dpk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
                            }
                        }
                    }
                }
            },
            "ApiKey": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "key_prefix": {
                        "type": "string"
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "allowed_game_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true
                    },
                    "allowed_stream_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true
                    },
                    "rate_limit_per_minute": {
                        "type": "integer"
                    },
                    "rate_limit_per_day": {
                        "type": "integer"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "SuccessResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    }
                }
            },
            "ErrorResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string",
                        "example": "Description of what went wrong"
                    }
                }
            }
        },
        "responses": {
            "BadRequest": {
                "description": "Missing or invalid parameters",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "Unauthorized": {
                "description": "Invalid or revoked API key / missing auth",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "API key does not have access to the requested resource",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Rate limit exceeded",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            }
        }
    }
}