{
  "openapi": "3.0.3",
  "info": {
    "title": "NexzLabs Developer API",
    "version": "1.0.0-beta",
    "description": "Monthly Creator/Pro and lifetime Lite/Starter. One active generation per account including Studio. 60 requests/min/account, 6 generation starts/min/account. Credits shared with Studio. Poll every 5 seconds. Single speaker and podcast MP3 output."
  },
  "servers": [
    {
      "url": "https://nexzlabs.com/api/v1"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "NL_live_..."
      }
    }
  },
  "paths": {
    "/voices": {
      "get": {
        "summary": "List current voices (100 per page)",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Plan, credits or account restricted"
          },
          "429": {
            "description": "Rate or capacity limit; respect Retry-After"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/usage": {
      "get": {
        "summary": "Read shared plan credits limit and usage",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Plan, credits or account restricted"
          },
          "429": {
            "description": "Rate or capacity limit; respect Retry-After"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        }
      }
    },
    "/generations": {
      "post": {
        "summary": "Create an asynchronous generation",
        "responses": {
          "200": {
            "description": "Existing idempotent job: id, status"
          },
          "202": {
            "description": "Accepted: id, status pending, progress 0"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Plan, credits or account restricted"
          },
          "409": {
            "description": "Idempotency key conflict"
          },
          "429": {
            "description": "Rate or capacity limit; respect Retry-After"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "New UUID per new job; same UUID and body on transport retries."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "voice_id"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100000
                  },
                  "voice_id": {
                    "type": "string",
                    "description": "Opaque id returned by /voices"
                  },
                  "speed": {
                    "type": "number",
                    "minimum": 0.25,
                    "maximum": 4,
                    "default": 1
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "single",
                      "podcast"
                    ],
                    "default": "single"
                  },
                  "speakers": {
                    "type": "array",
                    "minItems": 2,
                    "maxItems": 20,
                    "items": {
                      "type": "object",
                      "required": [
                        "id",
                        "name",
                        "voice_id"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^speaker_[1-9][0-9]{0,3}$"
                        },
                        "name": {
                          "type": "string",
                          "maxLength": 80
                        },
                        "voice_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/generations/{id}": {
      "get": {
        "summary": "Poll your job; completed response includes audio_url, expires_at, audio_duration_seconds and credits_used",
        "responses": {
          "200": {
            "description": "id, status (pending/completed/failed), progress, audio_url (nullable), audio_duration_seconds, expires_at, credits_used, optional sanitized error"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Plan, credits or account restricted"
          },
          "404": {
            "description": "Job not found"
          },
          "429": {
            "description": "Rate or capacity limit; respect Retry-After"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/generations/{id}/cancel": {
      "post": {
        "summary": "Cancel your pending job and release reserved credits",
        "responses": {
          "200": {
            "description": "cancelled: true"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Plan, credits or account restricted"
          },
          "404": {
            "description": "Job not found"
          },
          "409": {
            "description": "Already finalizing or terminal"
          },
          "429": {
            "description": "Rate or capacity limit; respect Retry-After"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    }
  }
}
