{
  "openapi": "3.0.3",
  "info": {
    "title": "SIPGPT User API",
    "version": "1.0.0",
    "description": "User-facing API for SIPGPT dashboard accounts, phone numbers, SIP resources, API keys, and SIPGPT chat actions. Authenticate with POST /auth/login, paste the returned token into Authorize, and send direct HTTP calls with Authorization: Bearer {token}."
  },
  "servers": [
    {
      "url": "https://app.sipgpt.co/api",
      "description": "SIPGPT production dashboard API"
    },
    {
      "url": "http://localhost:3002/api",
      "description": "Local dashboard API"
    }
  ],
  "tags": [
    { "name": "auth", "description": "Register, login, OTP verification, account selection, and current user details." },
    { "name": "account", "description": "Account, team members, invitations, roles, and permissions." },
    { "name": "settings", "description": "Account settings, preferences, and API keys." },
    { "name": "mcp", "description": "Create, test, audit, and revoke scoped connections for external AI clients." },
    { "name": "sipgpt", "description": "Natural-language SIPGPT actions with explicit confirmation." },
    { "name": "numbers", "description": "Search, purchase, list, renew, and inspect phone numbers." },
    { "name": "sip-trunks", "description": "Create and manage SIP trunks." },
    { "name": "sip-domains", "description": "Create and manage SIP domains, routing, and allowed source IPs." },
    { "name": "sip-users", "description": "Create and manage SIP users." }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Paste the token value returned by /auth/login or /auth/verify-otp."
      }
    },
    "schemas": {
      "LoginRequest": {
        "type": "object",
        "required": ["email", "password"],
        "properties": {
          "email": { "type": "string", "format": "email", "example": "john.doe@example.com" },
          "password": { "type": "string", "example": "password123" }
        }
      },
      "RegisterRequest": {
        "type": "object",
        "required": ["email", "password"],
        "properties": {
          "email": { "type": "string", "format": "email", "example": "john.doe@example.com" },
          "password": { "type": "string", "minLength": 6, "example": "password123" },
          "firstName": { "type": "string", "example": "John" },
          "lastName": { "type": "string", "example": "Doe" },
          "invitationToken": { "type": "string", "example": "inv_2ab9f0d3" }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "token": { "type": "string", "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." },
          "accountId": { "type": "integer", "example": 12 },
          "role": { "type": "string", "example": "owner" },
          "requiresAccountSelection": { "type": "boolean", "example": false },
          "user": { "$ref": "#/components/schemas/User" },
          "accounts": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/AccountSummary" }
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "example": 42 },
          "email": { "type": "string", "format": "email", "example": "john.doe@example.com" },
          "firstName": { "type": "string", "nullable": true, "example": "John" },
          "lastName": { "type": "string", "nullable": true, "example": "Doe" },
          "currentAccount": { "type": "integer", "nullable": true, "example": 12 }
        }
      },
      "AccountSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "example": 12 },
          "companyName": { "type": "string", "example": "John's Account" },
          "accountEmail": { "type": "string", "format": "email", "example": "john.doe@example.com" },
          "owner": { "type": "boolean", "example": true }
        }
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "properties": {
          "label": { "type": "string", "example": "Billing portal integration" },
          "expiresAt": { "type": "string", "format": "date-time", "example": "2027-01-31T23:59:59.000Z" }
        }
      },
      "ApiKeyResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "example": 7 },
          "label": { "type": "string", "nullable": true, "example": "Billing portal integration" },
          "preview": { "type": "string", "example": "sk_live_...Q4x9" },
          "apiKey": { "type": "string", "description": "Returned only when the key is created.", "example": "sk_live_2M8Wv3wO2vLmL4qTnZ9Q4x9" },
          "lastUsedAt": { "type": "string", "format": "date-time", "nullable": true },
          "expiresAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" },
          "revokedAt": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "SipGptChatRequest": {
        "type": "object",
        "required": ["message"],
        "properties": {
          "message": { "type": "string", "minLength": 1, "maxLength": 2000, "example": "Buy 3 California numbers with different prefixes." },
          "pendingActionId": { "type": "string", "example": "8dff0eb8-2ed9-4f6f-83b2-43de902bf8d1" }
        }
      },
      "SipGptResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "enum": ["needs_confirmation", "needs_clarification", "completed", "cancelled", "error"], "example": "needs_confirmation" },
          "message": { "type": "string", "example": "I found 3 numbers for you. Review them below and confirm before I place the order." },
          "action": { "$ref": "#/components/schemas/SipGptAction" },
          "result": { "type": "object", "additionalProperties": true }
        }
      },
      "SipGptAction": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "8dff0eb8-2ed9-4f6f-83b2-43de902bf8d1" },
          "type": { "type": "string", "enum": ["purchase_numbers", "route_did_to_trunk"], "example": "purchase_numbers" },
          "label": { "type": "string", "example": "Purchase phone numbers" },
          "summary": { "type": "string", "example": "Purchase 3 CA phone numbers with different prefixes" }
        }
      },
      "PhoneNumber": {
        "type": "object",
        "properties": {
          "did": { "type": "string", "example": "+12135550199" },
          "country": { "type": "string", "example": "US" },
          "state": { "type": "string", "example": "CA" },
          "rateCenter": { "type": "string", "example": "LOS ANGELES" },
          "monthlyFee": { "type": "number", "example": 1 },
          "setupFee": { "type": "number", "example": 0 },
          "currency": { "type": "string", "example": "USD" }
        }
      },
      "PurchaseNumberRequest": {
        "type": "object",
        "required": ["did", "vendorKey", "paymentMethod"],
        "properties": {
          "did": { "type": "string", "example": "+12135550199" },
          "vendorKey": { "type": "string", "example": "inteliquent" },
          "paymentMethod": { "type": "string", "enum": ["balance", "gateway"], "example": "balance" },
          "autoRenew": { "type": "boolean", "example": true }
        }
      },
      "SipTrunkRequest": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "example": "Primary office trunk" },
          "terminationUri": { "type": "string", "example": "sip:3.4.4.4:5060" },
          "outboundRouteType": { "type": "string", "enum": ["bring_own", "use_sipgpt"], "example": "bring_own" }
        }
      },
      "SipDomainRequest": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "example": "alma" },
          "authMode": { "type": "string", "enum": ["password", "ip"], "example": "password" },
          "routingTarget": { "type": "string", "enum": ["sipgpt", "sip_trunk", "agent"], "example": "sipgpt" }
        }
      },
      "SipUserRequest": {
        "type": "object",
        "properties": {
          "sipDomainId": { "type": "integer", "example": 4 },
          "username": { "type": "string", "example": "agent1001" },
          "displayName": { "type": "string", "example": "Agent 1001" },
          "password": { "type": "string", "description": "Optional. Generated when omitted.", "example": "Use-Strong-Password-123" }
        }
      },
      "MessageResponse": {
        "type": "object",
        "properties": {
          "message": { "type": "string", "example": "OK" }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "statusCode": { "type": "integer", "example": 400 },
          "message": { "type": "string", "example": "Validation failed" },
          "error": { "type": "string", "example": "Bad Request" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid bearer token.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      }
    }
  },
  "paths": {
    "/auth/register": {
      "post": {
        "tags": ["auth"],
        "summary": "Register a new user",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequest" } } }
        },
        "responses": {
          "200": {
            "description": "Registration succeeded. Verify the OTP sent by email.",
            "content": { "application/json": { "example": { "message": "Registration successful. Please check your email for OTP verification.", "email": "john.doe@example.com" } } }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": ["auth"],
        "summary": "Log in with email and password",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } }
        },
        "responses": {
          "200": {
            "description": "Returns a JWT token or an OTP-required response.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TokenResponse" },
                "examples": {
                  "authenticated": { "value": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "accountId": 12, "role": "owner", "requiresAccountSelection": false, "user": { "id": 42, "email": "john.doe@example.com", "firstName": "John", "lastName": "Doe", "currentAccount": 12 }, "accounts": [{ "id": 12, "companyName": "John's Account", "accountEmail": "john.doe@example.com", "owner": true }] } },
                  "verificationRequired": { "value": { "requiresVerification": true, "email": "john.doe@example.com", "message": "Email not verified. Please enter the OTP sent to your email." } }
                }
              }
            }
          }
        }
      }
    },
    "/auth/verify-otp": {
      "post": {
        "tags": ["auth"],
        "summary": "Verify email OTP",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["email", "otpCode"], "properties": { "email": { "type": "string", "format": "email", "example": "john.doe@example.com" }, "otpCode": { "type": "string", "minLength": 6, "maxLength": 6, "example": "123456" } } } } }
        },
        "responses": { "200": { "description": "Email verified.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenResponse" } } } } }
      }
    },
    "/auth/resend-otp": {
      "post": {
        "tags": ["auth"],
        "summary": "Resend OTP email",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email", "example": "john.doe@example.com" } } } } } },
        "responses": { "200": { "description": "OTP resent.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } } }
      }
    },
    "/auth/select-account": {
      "post": {
        "tags": ["auth"],
        "summary": "Switch the active account",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["accountId"], "properties": { "accountId": { "type": "integer", "example": 12 } } } } } },
        "responses": { "200": { "description": "Fresh token scoped to the selected account.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenResponse" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/auth/me": {
      "get": {
        "tags": ["auth"],
        "summary": "Current user, accounts, role, and permissions",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Current user context." }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/account": {
      "post": {
        "tags": ["account"],
        "summary": "Create a new account owned by the current user",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["companyName"], "properties": { "companyName": { "type": "string", "example": "Acme Voice LLC" } } } } } },
        "responses": { "201": { "description": "Account created." }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/account/members": {
      "get": {
        "tags": ["account"],
        "summary": "List account members",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Account members." }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/account/invitations": {
      "get": {
        "tags": ["account"],
        "summary": "List account invitations",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Pending invitations." } }
      },
      "post": {
        "tags": ["account"],
        "summary": "Invite a user to the account",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email", "role"], "properties": { "email": { "type": "string", "format": "email", "example": "teammate@example.com" }, "role": { "type": "string", "example": "member" } } } } } },
        "responses": { "201": { "description": "Invitation created." } }
      }
    },
    "/settings/account": {
      "get": {
        "tags": ["settings"],
        "summary": "Get account-level settings",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Account settings." } }
      },
      "patch": {
        "tags": ["settings"],
        "summary": "Update account-level settings",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "companyName": { "type": "string", "example": "Acme Voice LLC" }, "accountEmail": { "type": "string", "format": "email", "example": "billing@example.com" }, "defaultCallerId": { "type": "string", "example": "+12135550199" } } } } } },
        "responses": { "200": { "description": "Updated account settings." } }
      }
    },
    "/settings/api-keys": {
      "get": {
        "tags": ["settings"],
        "summary": "List API keys for the current account",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "API key list.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ApiKeyResponse" } } } } } }
      },
      "post": {
        "tags": ["settings"],
        "summary": "Create an API key. The raw key is returned once.",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateApiKeyRequest" } } } },
        "responses": { "201": { "description": "API key created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKeyResponse" } } } } }
      }
    },
    "/v1/mcp/metadata": {
      "get": {
        "tags": ["mcp"],
        "summary": "Get MCP availability, clients, scopes, and endpoint metadata",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Account-specific MCP connection metadata." }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/v1/mcp/connections": {
      "get": {
        "tags": ["mcp"],
        "summary": "List MCP connections for the current account",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Active and revoked connection summaries. Raw secrets are never returned." } }
      },
      "post": {
        "tags": ["mcp"],
        "summary": "Create a least-privilege MCP connection",
        "description": "The raw connection secret is returned once. Write scopes allow preparation only; cost- or traffic-impacting changes still require explicit confirmation.",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["client", "name", "scopes"], "properties": { "client": { "type": "string", "enum": ["codex", "claude", "cursor", "vscode", "other"], "example": "codex" }, "name": { "type": "string", "example": "My Codex connection" }, "scopes": { "type": "array", "uniqueItems": true, "items": { "type": "string", "enum": ["numbers:read", "sip:read", "numbers:purchase", "routing:write", "cdr:read"] }, "example": ["numbers:read", "sip:read"] } } } } } },
        "responses": { "201": { "description": "Connection created; copy the one-time secret now." }, "401": { "$ref": "#/components/responses/Unauthorized" } }
      }
    },
    "/v1/mcp/connections/{id}/test": {
      "post": {
        "tags": ["mcp"],
        "summary": "Test an MCP connection",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Connection health and tool-discovery result." } }
      }
    },
    "/v1/mcp/connections/{id}": {
      "delete": {
        "tags": ["mcp"],
        "summary": "Revoke an MCP connection",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "204": { "description": "Connection revoked." } }
      }
    },
    "/v1/mcp/connections/{id}/activity": {
      "get": {
        "tags": ["mcp"],
        "summary": "Get recent MCP connection activity",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Account-scoped activity records without secrets." } }
      }
    },
    "/v1/sipgpt/capabilities": {
      "get": {
        "tags": ["sipgpt"],
        "summary": "Get available SIPGPT tools and quick-action capabilities",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Capabilities filtered by account role and permissions." } }
      }
    },
    "/v1/sipgpt/sessions": {
      "get": {
        "tags": ["sipgpt"],
        "summary": "List the current user's SIPGPT sessions",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "Account- and user-scoped sessions." } }
      },
      "post": {
        "tags": ["sipgpt"],
        "summary": "Create a SIPGPT session",
        "security": [{ "bearer": [] }],
        "responses": { "201": { "description": "Session created." } }
      }
    },
    "/v1/sipgpt/sessions/{sessionId}": {
      "get": {
        "tags": ["sipgpt"],
        "summary": "Get a SIPGPT session and its persisted messages",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "sessionId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Session, runs, messages, artifacts, and pending actions." } }
      }
    },
    "/v1/sipgpt/sessions/{sessionId}/events": {
      "get": {
        "tags": ["sipgpt"],
        "summary": "Poll resumable SIPGPT session events",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "sessionId", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "after", "in": "query", "description": "Opaque cursor from the last received event.", "schema": { "type": "string" } }],
        "responses": { "200": { "description": "A bounded batch of events and the next cursor." } }
      }
    },
    "/v1/sipgpt/chat": {
      "post": {
        "tags": ["sipgpt"],
        "summary": "Send a message to a SIPGPT session",
        "security": [{ "bearer": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SipGptChatRequest" },
              "examples": {
                "purchaseNumbers": { "value": { "message": "Buy 3 California numbers with different prefixes." } },
                "routeDid": { "value": { "message": "Send calls to 2135550199 to trunk IP 3.4.4.4." } },
                "idempotentMessage": { "value": { "sessionId": "43d58602-e4d4-429f-8f8b-9ad03f89ac87", "clientMessageId": "msg-20260727-001", "message": "Buy 3 California numbers with different prefixes." } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Clarification, pending action, or completed result.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipGptResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/sipgpt/actions/{id}": {
      "get": {
        "tags": ["sipgpt"],
        "summary": "Get the current state of a SIPGPT action",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Pending, completed, cancelled, expired, or failed action." } }
      }
    },
    "/v1/sipgpt/actions/{id}/confirm": {
      "post": {
        "tags": ["sipgpt"],
        "summary": "Confirm and execute a pending SIPGPT action",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "8dff0eb8-2ed9-4f6f-83b2-43de902bf8d1" }],
        "responses": { "200": { "description": "Action completed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipGptResponse" } } } } }
      }
    },
    "/v1/sipgpt/actions/{id}/cancel": {
      "post": {
        "tags": ["sipgpt"],
        "summary": "Cancel a pending SIPGPT action",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "8dff0eb8-2ed9-4f6f-83b2-43de902bf8d1" }],
        "responses": { "200": { "description": "Action cancelled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipGptResponse" } } } } }
      }
    },
    "/numbers": {
      "get": {
        "tags": ["numbers"],
        "summary": "List the current account's connected phone numbers",
        "security": [{ "bearer": [] }],
        "parameters": [
          { "name": "country", "in": "query", "schema": { "type": "string" }, "example": "US" },
          { "name": "state", "in": "query", "schema": { "type": "string" }, "example": "CA" }
        ],
        "responses": { "200": { "description": "Phone number assignments." } }
      }
    },
    "/numbers/search/local": {
      "get": {
        "tags": ["numbers"],
        "summary": "Search local DIDs by country, state, rate center, NPA, or NXX",
        "security": [{ "bearer": [] }],
        "parameters": [
          { "name": "country", "in": "query", "schema": { "type": "string" }, "example": "US" },
          { "name": "state", "in": "query", "schema": { "type": "string" }, "example": "CA" },
          { "name": "npa", "in": "query", "schema": { "type": "string" }, "example": "213" },
          { "name": "limit", "in": "query", "schema": { "type": "integer" }, "example": 10 }
        ],
        "responses": { "200": { "description": "Available numbers.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/PhoneNumber" } } } } } }
      }
    },
    "/numbers/purchase": {
      "post": {
        "tags": ["numbers"],
        "summary": "Purchase a DID",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PurchaseNumberRequest" } } } },
        "responses": { "201": { "description": "Number purchased or checkout URL returned." } }
      }
    },
    "/numbers/lookup": {
      "get": {
        "tags": ["numbers"],
        "summary": "Look up a US number's carrier, geography, and risk profile",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "tn", "in": "query", "required": true, "schema": { "type": "string" }, "example": "+12135550199" }],
        "responses": { "200": { "description": "Lookup result." } }
      }
    },
    "/sip-trunks": {
      "get": {
        "tags": ["sip-trunks"],
        "summary": "List SIP trunks",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "SIP trunks." } }
      },
      "post": {
        "tags": ["sip-trunks"],
        "summary": "Create a SIP trunk",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipTrunkRequest" } } } },
        "responses": { "201": { "description": "SIP trunk created." } }
      }
    },
    "/sip-trunks/{id}": {
      "get": {
        "tags": ["sip-trunks"],
        "summary": "Get a SIP trunk",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "SIP trunk." } }
      },
      "patch": {
        "tags": ["sip-trunks"],
        "summary": "Update a SIP trunk",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipTrunkRequest" } } } },
        "responses": { "200": { "description": "SIP trunk updated." } }
      },
      "delete": {
        "tags": ["sip-trunks"],
        "summary": "Delete a SIP trunk",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "SIP trunk deleted." } }
      }
    },
    "/sip-domains": {
      "get": {
        "tags": ["sip-domains"],
        "summary": "List SIP domains",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "SIP domains." } }
      },
      "post": {
        "tags": ["sip-domains"],
        "summary": "Create a SIP domain",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipDomainRequest" } } } },
        "responses": { "201": { "description": "SIP domain created." } }
      }
    },
    "/sip-domains/availability": {
      "get": {
        "tags": ["sip-domains"],
        "summary": "Check whether a SIP domain name is available",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "name", "in": "query", "schema": { "type": "string" }, "example": "alma" }],
        "responses": { "200": { "description": "Availability result." } }
      }
    },
    "/sip-domains/{id}/routing": {
      "patch": {
        "tags": ["sip-domains"],
        "summary": "Update inbound routing for a SIP domain",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "routingTarget": { "type": "string", "enum": ["sipgpt", "sip_trunk", "agent"], "example": "sipgpt" }, "routingSipTrunkId": { "type": "integer", "example": 8 }, "routingAgentId": { "type": "integer", "example": 3 } } } } } },
        "responses": { "200": { "description": "Routing updated." } }
      }
    },
    "/sip-users": {
      "get": {
        "tags": ["sip-users"],
        "summary": "List SIP users",
        "security": [{ "bearer": [] }],
        "responses": { "200": { "description": "SIP users." } }
      },
      "post": {
        "tags": ["sip-users"],
        "summary": "Create a SIP user. Generated password is returned once.",
        "security": [{ "bearer": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SipUserRequest" } } } },
        "responses": { "201": { "description": "SIP user created." } }
      }
    },
    "/sip-users/{id}/reset-password": {
      "post": {
        "tags": ["sip-users"],
        "summary": "Reset a SIP user password. Generated password is returned once.",
        "security": [{ "bearer": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "Password reset result." } }
      }
    }
  }
}
