{
  "openapi": "3.1.0",
  "info": {
    "title": "FlashAuth API",
    "version": "1.0.0",
    "description": "\nPhone OTP auth and JWT sessions. Send `x-api-key` on each request — `pk_live_` for real SMS, `pk_test_` for sandbox (codes show in the dashboard).\n\nCodes expire in 5 minutes. 30s resend cooldown. Max 5 failed attempts per challenge.\n    ",
    "termsOfService": "https://flashauth.dev/terms",
    "contact": {
      "name": "FlashAuth Developer Support",
      "url": "https://flashauth.dev",
      "email": "support@flashauth.dev"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "servers": [
    {
      "url": "https://api.flashauth.dev",
      "description": "Production"
    },
    {
      "url": "http://localhost:4000",
      "description": "Local"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "OTP Verification",
      "description": "Send, verify, and resend SMS OTPs."
    },
    {
      "name": "Authentication & Sessions",
      "description": "Turn a verified OTP into JWT session tokens."
    },
    {
      "name": "Projects & Developers",
      "description": "Apps, API keys, and project settings."
    },
    {
      "name": "Analytics & Logs",
      "description": "Request logs and delivery metrics."
    },
    {
      "name": "Test Sandbox",
      "description": "View test OTP codes (no SMS)."
    },
    {
      "name": "Billing & Credits",
      "description": "OTP credits and quotas."
    }
  ],
  "paths": {
    "/v1/otp/send": {
      "post": {
        "tags": [
          "OTP Verification"
        ],
        "summary": "Send OTP code",
        "operationId": "sendOtp",
        "description": "Send an OTP to an E.164 phone number. Returns `verification_id` and expiry.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Recipient phone number.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendOtpRequest"
              },
              "example": {
                "phone": "+9198765xxxxx"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OTP sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendOtpResponse"
                },
                "example": {
                  "success": true,
                  "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
                  "expires_at": "2026-10-02T01:35:00.000Z",
                  "channel": "sms",
                  "cooldown_seconds": 30
                }
              }
            }
          },
          "400": {
            "description": "Invalid or unsupported phone number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Bad Request",
                  "message": "Invalid phone number format. Must adhere to E.164 (e.g. +9198765xxxxx)."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or revoked API key provided."
                }
              }
            }
          },
          "429": {
            "description": "Cooldown active or quota exhausted.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until resend cooldown expires.",
                "schema": {
                  "type": "integer",
                  "example": 28
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CooldownErrorResponse"
                },
                "example": {
                  "error": "Too Many Requests",
                  "message": "Resend cooldown active. Wait 28s before requesting a new code.",
                  "retry_after_seconds": 28
                }
              }
            }
          }
        }
      }
    },
    "/v1/otp/verify": {
      "post": {
        "tags": [
          "OTP Verification"
        ],
        "summary": "Verify OTP code",
        "operationId": "verifyOtp",
        "description": "Check the OTP against the active challenge. In test mode, copy the code from Sandbox.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Phone number and received numeric OTP code.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyOtpRequest"
              },
              "example": {
                "phone": "+9198765xxxxx",
                "code": "8492"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code verified successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyOtpResponse"
                },
                "example": {
                  "verified": true,
                  "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
                  "phone": "+9198765xxxxx"
                }
              }
            }
          },
          "400": {
            "description": "Incorrect verification code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyFailedResponse"
                },
                "example": {
                  "verified": false,
                  "error": "Invalid code",
                  "message": "The code entered does not match.",
                  "attempts_remaining": 4
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Challenge expired or not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Not Found",
                  "message": "No active verification challenge found for this phone number."
                }
              }
            }
          },
          "429": {
            "description": "Maximum verification attempts exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Too Many Requests",
                  "message": "Verification challenge locked. Maximum attempts exceeded."
                }
              }
            }
          }
        }
      }
    },
    "/v1/otp/resend": {
      "post": {
        "tags": [
          "OTP Verification"
        ],
        "summary": "Resend OTP code",
        "operationId": "resendOtp",
        "description": "Resend OTP for a `verification_id`. Subject to the 30s cooldown.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResendOtpRequest"
              },
              "example": {
                "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code resent successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendOtpResponse"
                },
                "example": {
                  "success": true,
                  "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
                  "expires_at": "2026-10-02T01:35:00.000Z",
                  "channel": "sms",
                  "cooldown_seconds": 30
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired verification challenge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Cooldown active. Must wait before resending.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CooldownErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/signup": {
      "post": {
        "tags": [
          "Authentication & Sessions"
        ],
        "summary": "Sign up user",
        "operationId": "authSignup",
        "description": "Create a user from a verified OTP and return JWT tokens.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthSessionRequest"
              },
              "example": {
                "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User created and tokens issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthSessionResponse"
                },
                "example": {
                  "user": {
                    "id": "usr_9b1deb4d3b7d",
                    "phone": "+9198765xxxxx",
                    "created_at": "2026-10-02T01:00:00.000Z"
                  },
                  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "refresh_token": "rf_9f83a04bc8d2e1...",
                  "token_type": "Bearer",
                  "expires_in": 3600
                }
              }
            }
          },
          "400": {
            "description": "Challenge not verified or already used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/login": {
      "post": {
        "tags": [
          "Authentication & Sessions"
        ],
        "summary": "Log in user",
        "operationId": "authLogin",
        "description": "Log in an existing user with a verified OTP and return JWT tokens.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthSessionRequest"
              },
              "example": {
                "verification_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session tokens issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthSessionResponse"
                },
                "example": {
                  "user": {
                    "id": "usr_9b1deb4d3b7d",
                    "phone": "+9198765xxxxx",
                    "created_at": "2026-10-02T01:00:00.000Z"
                  },
                  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "refresh_token": "rf_9f83a04bc8d2e1...",
                  "token_type": "Bearer",
                  "expires_in": 3600
                }
              }
            }
          },
          "400": {
            "description": "Challenge not verified or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/refresh": {
      "post": {
        "tags": [
          "Authentication & Sessions"
        ],
        "summary": "Refresh access token",
        "operationId": "authRefresh",
        "description": "Exchange a refresh token for a new access token.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshTokenRequest"
              },
              "example": {
                "refresh_token": "rf_9f83a04bc8d2e1..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "New access token generated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefreshTokenResponse"
                },
                "example": {
                  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "refresh_token": "rf_new_9f83a04bc8d...",
                  "token_type": "Bearer",
                  "expires_in": 3600
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked refresh token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/logout": {
      "post": {
        "tags": [
          "Authentication & Sessions"
        ],
        "summary": "Log out user",
        "operationId": "authLogout",
        "description": "Revoke a refresh token session.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshTokenRequest"
              },
              "example": {
                "refresh_token": "rf_9f83a04bc8d2e1..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session revoked successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "List projects",
        "operationId": "listProjects",
        "description": "List all projects for the signed-in developer.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of developer projects.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Create project",
        "operationId": "createProject",
        "description": "Create a new project.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Production Storefront"
                  },
                  "allowedCountries": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "IN",
                      "US"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}": {
      "get": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Get project",
        "operationId": "getProject",
        "description": "Get project config and quota.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project identifier UUID."
          }
        ],
        "responses": {
          "200": {
            "description": "Project configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Update project",
        "operationId": "updateProject",
        "description": "Update project settings (countries, SMS text).",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "allowedCountries": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "smsIntro": {
                    "type": "string",
                    "example": "is your verification code"
                  },
                  "smsBrandFooter": {
                    "type": "string",
                    "example": "Valid for 5 mins."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Delete project",
        "operationId": "deleteProject",
        "description": "Delete a project and its keys.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/api-keys": {
      "get": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "List API keys",
        "operationId": "listApiKeys",
        "description": "List API keys for a project.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of API keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKeyItem"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Create API key",
        "operationId": "createApiKey",
        "description": "Create a `pk_live_` or `pk_test_` key. Secret shown once.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "environment"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Production Backend"
                  },
                  "environment": {
                    "type": "string",
                    "enum": [
                      "live",
                      "test"
                    ],
                    "example": "live"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key generated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "$ref": "#/components/schemas/ApiKeyItem"
                    },
                    "secretKey": {
                      "type": "string",
                      "example": "pk_live_9f83a04bc8d2e1b4c9e8a7d6",
                      "description": "Full secret — copy and store it now."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/api-keys/{keyId}": {
      "delete": {
        "tags": [
          "Projects & Developers"
        ],
        "summary": "Revoke API key",
        "operationId": "revokeApiKey",
        "description": "Revoke an API key.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "API key revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/usage": {
      "get": {
        "tags": [
          "Analytics & Logs"
        ],
        "summary": "Get project usage",
        "operationId": "getProjectUsage",
        "description": "Quota used and remaining OTP credits.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "quota": {
                          "type": "integer",
                          "example": 1500
                        },
                        "used": {
                          "type": "integer",
                          "example": 420
                        },
                        "remaining": {
                          "type": "integer",
                          "example": 1080
                        },
                        "freeRemaining": {
                          "type": "integer",
                          "example": 50
                        },
                        "paidRemaining": {
                          "type": "integer",
                          "example": 1030
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/logs": {
      "get": {
        "tags": [
          "Analytics & Logs"
        ],
        "summary": "Query request logs",
        "operationId": "getProjectLogs",
        "description": "Recent API logs with status and latency.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "success",
                "error",
                "rate_limited"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent logs list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "logs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "method": {
                            "type": "string",
                            "example": "POST"
                          },
                          "path": {
                            "type": "string",
                            "example": "/v1/otp/send"
                          },
                          "statusCode": {
                            "type": "integer",
                            "example": 200
                          },
                          "durationMs": {
                            "type": "integer",
                            "example": 142
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/test-otps": {
      "get": {
        "tags": [
          "Test Sandbox"
        ],
        "summary": "Get test OTP inbox",
        "operationId": "getTestOtps",
        "description": "List test OTPs from `pk_test_` calls. Copy the code to verify.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Test OTP inbox list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "challenges": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "phoneE164": {
                            "type": "string",
                            "example": "+9198765xxxxx"
                          },
                          "code": {
                            "type": "string",
                            "example": "849201"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "verified",
                              "expired"
                            ]
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "expiresAt": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/config": {
      "get": {
        "tags": [
          "Billing & Credits"
        ],
        "summary": "Get billing tiers",
        "operationId": "getBillingConfig",
        "description": "Credit pack prices and payment details.",
        "responses": {
          "200": {
            "description": "Pricing configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string",
                      "example": "INR"
                    },
                    "costPerOtp": {
                      "type": "number",
                      "example": 0.32
                    },
                    "minCredits": {
                      "type": "integer",
                      "example": 500
                    },
                    "maxCredits": {
                      "type": "integer",
                      "example": 500000
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "`pk_live_` for SMS, `pk_test_` for sandbox."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Developer console session token."
      }
    },
    "schemas": {
      "SendOtpRequest": {
        "type": "object",
        "required": [
          "phone"
        ],
        "properties": {
          "phone": {
            "type": "string",
            "format": "e164",
            "description": "Phone in E.164 (e.g. +9198765xxxxx).",
            "example": "+9198765xxxxx"
          }
        }
      },
      "SendOtpResponse": {
        "type": "object",
        "required": [
          "success",
          "verification_id",
          "expires_at",
          "cooldown_seconds"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "verification_id": {
            "type": "string",
            "format": "uuid",
            "description": "Challenge ID from /send.",
            "example": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the code expires (5 min).",
            "example": "2026-10-02T01:35:00.000Z"
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms",
              "whatsapp"
            ],
            "default": "sms",
            "example": "sms"
          },
          "cooldown_seconds": {
            "type": "integer",
            "description": "Seconds until another OTP can be sent.",
            "example": 30
          }
        }
      },
      "VerifyOtpRequest": {
        "type": "object",
        "required": [
          "phone",
          "code"
        ],
        "properties": {
          "phone": {
            "type": "string",
            "description": "Phone in E.164.",
            "example": "+9198765xxxxx"
          },
          "code": {
            "type": "string",
            "description": "OTP code from SMS or Sandbox.",
            "example": "8492"
          }
        }
      },
      "VerifyOtpResponse": {
        "type": "object",
        "required": [
          "verified",
          "verification_id",
          "phone"
        ],
        "properties": {
          "verified": {
            "type": "boolean",
            "example": true
          },
          "verification_id": {
            "type": "string",
            "format": "uuid",
            "example": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
          },
          "phone": {
            "type": "string",
            "example": "+9198765xxxxx"
          }
        }
      },
      "ResendOtpRequest": {
        "type": "object",
        "required": [
          "verification_id"
        ],
        "properties": {
          "verification_id": {
            "type": "string",
            "format": "uuid",
            "example": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
          }
        }
      },
      "AuthSessionRequest": {
        "type": "object",
        "required": [
          "verification_id"
        ],
        "properties": {
          "verification_id": {
            "type": "string",
            "format": "uuid",
            "description": "Verified challenge ID.",
            "example": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
          }
        }
      },
      "AuthSessionResponse": {
        "type": "object",
        "required": [
          "user",
          "access_token",
          "refresh_token",
          "token_type",
          "expires_in"
        ],
        "properties": {
          "user": {
            "type": "object",
            "required": [
              "id",
              "phone",
              "created_at"
            ],
            "properties": {
              "id": {
                "type": "string",
                "example": "usr_9b1deb4d3b7d"
              },
              "phone": {
                "type": "string",
                "example": "+9198765xxxxx"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "access_token": {
            "type": "string",
            "description": "JWT access token.",
            "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
          },
          "refresh_token": {
            "type": "string",
            "description": "Refresh token for new access tokens.",
            "example": "rf_9f83a04bc8d2e1..."
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "description": "Access token lifetime in seconds.",
            "example": 3600
          }
        }
      },
      "RefreshTokenRequest": {
        "type": "object",
        "required": [
          "refresh_token"
        ],
        "properties": {
          "refresh_token": {
            "type": "string",
            "example": "rf_9f83a04bc8d2e1..."
          }
        }
      },
      "RefreshTokenResponse": {
        "type": "object",
        "required": [
          "access_token",
          "refresh_token",
          "token_type",
          "expires_in"
        ],
        "properties": {
          "access_token": {
            "type": "string",
            "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
          },
          "refresh_token": {
            "type": "string",
            "example": "rf_new_9f83a04bc8d..."
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "example": 3600
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "monthlyOtpQuota",
          "monthlyOtpUsed"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "proj_9b1deb4d3b7d"
          },
          "name": {
            "type": "string",
            "example": "Production App"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended"
            ],
            "example": "active"
          },
          "monthlyOtpQuota": {
            "type": "integer",
            "example": 1500
          },
          "monthlyOtpUsed": {
            "type": "integer",
            "example": 215
          },
          "allowedCountries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "IN"
            ]
          },
          "smsIntro": {
            "type": "string",
            "nullable": true
          },
          "smsBrandFooter": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApiKeyItem": {
        "type": "object",
        "required": [
          "id",
          "name",
          "keyPrefix",
          "environment",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "key_9b1deb4d3b7d"
          },
          "name": {
            "type": "string",
            "example": "Production Backend"
          },
          "keyPrefix": {
            "type": "string",
            "example": "pk_live_9f83..."
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "example": "live"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "VerifyFailedResponse": {
        "type": "object",
        "required": [
          "verified",
          "error",
          "message",
          "attempts_remaining"
        ],
        "properties": {
          "verified": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string",
            "example": "Invalid code"
          },
          "message": {
            "type": "string",
            "example": "The code entered does not match."
          },
          "attempts_remaining": {
            "type": "integer",
            "example": 4
          }
        }
      },
      "CooldownErrorResponse": {
        "type": "object",
        "required": [
          "error",
          "message",
          "retry_after_seconds"
        ],
        "properties": {
          "error": {
            "type": "string",
            "example": "Too Many Requests"
          },
          "message": {
            "type": "string",
            "example": "Resend cooldown active. Wait 28s before requesting a new code."
          },
          "retry_after_seconds": {
            "type": "integer",
            "example": 28
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "example": "Bad Request"
          },
          "message": {
            "type": "string",
            "example": "An error occurred while processing the request."
          }
        }
      }
    }
  }
}
