{
  "openapi": "3.1.0",
  "info": {
    "title": "Transcript+ API (Seenly)",
    "version": "0.1.0",
    "summary": "Audio/video → diarized transcript, summary, chapters and SRT/VTT captions. Pay per audio minute with x402.",
    "description": "Send a direct audio/video URL or a small upload. The service measures the duration, quotes the price, and after payment returns a speaker-labelled transcript, a structured summary and captions. Pricing: $0.01 USDC per audio minute via x402 on Base mainnet, minimum 1 minute. Billing is per started minute (1 s grace), minimum 1 minute. The unpaid call returns HTTP 402 with an x402 v2 PAYMENT-REQUIRED header whose amount is the exact total for your file, plus a JSON quote. Retry the same request with PAYMENT-SIGNATURE. Input is validated (and the URL fetched and measured) before any payment is requested; x402 settles only after a successful response. Limits: 60 min, URL 100 MB, upload 4 MB. Media is deleted after processing; nothing is stored.",
    "contact": {
      "name": "Seenly / Agentropolis",
      "email": "hello@agentropolis.io",
      "url": "https://www.seenly.live"
    },
    "x-guidance": "POST https://seenly-transcript-plus.vercel.app/api/transcribe with JSON {\"url\": \"https://.../file.mp3\"} (direct link to an audio/video file, up to 100 MB and 60 min) or {\"file\": {\"base64\": \"...\", \"filename\": \"a.m4a\"}} / multipart field \"file\" / a raw audio/* body (up to 4 MB). Options: diarize (default true), summary (default true), language (e.g. \"en-US\", auto-detected if omitted), style clean|verbatim, keywords [..] (spelling hints), maxMinutes (budget cap), includeWords, format json|srt|vtt|text. Price: $0.01 USDC per started audio minute (minimum 1 minute). The unpaid call measures the file and returns HTTP 402 with the exact amount in PAYMENT-REQUIRED and a JSON \"quote\"; sign it with any x402 client and retry the SAME request with PAYMENT-SIGNATURE. Bad input, unreachable URLs, files over the limits or over maxMinutes are rejected with 4xx before any payment; x402 settles only after a successful response. Only send media you have the right to process (recording consent is your responsibility). Media is deleted after processing; nothing is stored."
  },
  "servers": [
    {
      "url": "https://seenly-transcript-plus.vercel.app"
    }
  ],
  "x-pricing": {
    "status": "live",
    "unit": "audio_minute",
    "pricePerMinuteUsd": "0.01",
    "minimumMinutes": 1,
    "rail": {
      "protocol": "x402",
      "version": 2,
      "scheme": "exact",
      "network": "eip155:8453",
      "networkName": "Base mainnet",
      "asset": "USDC",
      "assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amountPerMinute": "10000",
      "payTo": "0xeE6239F3E17bEBe5e89F21F29D74D68CAa0d78CE",
      "facilitator": "Coinbase CDP (gas sponsored; payer needs USDC only, no ETH)",
      "header": "PAYMENT-SIGNATURE"
    }
  },
  "paths": {
    "/api/transcribe": {
      "get": {
        "operationId": "describeTranscribeEndpoint",
        "summary": "Free: short description of the POST endpoint",
        "security": [],
        "responses": {
          "200": {
            "description": "Endpoint hint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTranscript",
        "summary": "Transcribe audio/video with speakers, summary and captions",
        "description": "POST https://seenly-transcript-plus.vercel.app/api/transcribe with JSON {\"url\": \"https://.../file.mp3\"} (direct link to an audio/video file, up to 100 MB and 60 min) or {\"file\": {\"base64\": \"...\", \"filename\": \"a.m4a\"}} / multipart field \"file\" / a raw audio/* body (up to 4 MB). Options: diarize (default true), summary (default true), language (e.g. \"en-US\", auto-detected if omitted), style clean|verbatim, keywords [..] (spelling hints), maxMinutes (budget cap), includeWords, format json|srt|vtt|text. Price: $0.01 USDC per started audio minute (minimum 1 minute). The unpaid call measures the file and returns HTTP 402 with the exact amount in PAYMENT-REQUIRED and a JSON \"quote\"; sign it with any x402 client and retry the SAME request with PAYMENT-SIGNATURE. Bad input, unreachable URLs, files over the limits or over maxMinutes are rejected with 4xx before any payment; x402 settles only after a successful response. Only send media you have the right to process (recording consent is your responsibility). Media is deleted after processing; nothing is stored.",
        "x-payment-info": {
          "protocol": "x402",
          "pricing": "per audio minute",
          "pricePerMinuteUsd": "0.01",
          "rails": [
            {
              "protocol": "x402",
              "version": 2,
              "scheme": "exact",
              "network": "eip155:8453",
              "networkName": "Base mainnet",
              "asset": "USDC",
              "assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
              "amountPerMinute": "10000",
              "payTo": "0xeE6239F3E17bEBe5e89F21F29D74D68CAa0d78CE",
              "facilitator": "Coinbase CDP (gas sponsored; payer needs USDC only, no ETH)",
              "header": "PAYMENT-SIGNATURE",
              "priceUsd": "0.01",
              "unit": "audio_minute"
            }
          ],
          "chargedOn": "x402 settles only after a successful (2xx) response; failed calls are not charged."
        },
        "parameters": [
          {
            "name": "diarize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true,
              "description": "Label speakers (S1, S2, ...)."
            },
            "description": "Label speakers (S1, S2, ...). (Also accepted in the body.)"
          },
          {
            "name": "summary",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true,
              "description": "Add title, summary, key points, chapters, action items, topics."
            },
            "description": "Add title, summary, key points, chapters, action items, topics. (Also accepted in the body.)"
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "en-US",
              "description": "Locale hint. Omit for automatic language detection (60 languages)."
            },
            "description": "Locale hint. Omit for automatic language detection (60 languages). (Also accepted in the body.)"
          },
          {
            "name": "style",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "clean",
                "verbatim"
              ],
              "default": "clean",
              "description": "clean removes fillers; verbatim keeps them."
            },
            "description": "clean removes fillers; verbatim keeps them. (Also accepted in the body.)"
          },
          {
            "name": "keywords",
            "in": "query",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 50
              },
              "maxItems": 50,
              "description": "Names/terms to bias recognition toward."
            },
            "description": "Names/terms to bias recognition toward. (Also accepted in the body.)"
          },
          {
            "name": "maxMinutes",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 600,
              "description": "Budget cap: refuse (422, before payment) if the audio bills more minutes."
            },
            "description": "Budget cap: refuse (422, before payment) if the audio bills more minutes. (Also accepted in the body.)"
          },
          {
            "name": "includeWords",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "description": "Include word-level timings."
            },
            "description": "Include word-level timings. (Also accepted in the body.)"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "srt",
                "vtt",
                "text"
              ],
              "default": "json",
              "description": "json (everything), or just srt / vtt / text."
            },
            "description": "json (everything), or just srt / vtt / text. (Also accepted in the body.)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscribeRequest"
              },
              "example": {
                "url": "https://archive.org/download/doctordolittledramatic_1511_librivox/doctordolittle_01_lofting_64kb.mp3",
                "diarize": true,
                "summary": true
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "diarize": {
                    "type": "boolean",
                    "default": true,
                    "description": "Label speakers (S1, S2, ...)."
                  },
                  "summary": {
                    "type": "boolean",
                    "default": true,
                    "description": "Add title, summary, key points, chapters, action items, topics."
                  },
                  "language": {
                    "type": "string",
                    "example": "en-US",
                    "description": "Locale hint. Omit for automatic language detection (60 languages)."
                  },
                  "style": {
                    "type": "string",
                    "enum": [
                      "clean",
                      "verbatim"
                    ],
                    "default": "clean",
                    "description": "clean removes fillers; verbatim keeps them."
                  },
                  "keywords": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 50
                    },
                    "maxItems": 50,
                    "description": "Names/terms to bias recognition toward."
                  },
                  "maxMinutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 600,
                    "description": "Budget cap: refuse (422, before payment) if the audio bills more minutes."
                  },
                  "includeWords": {
                    "type": "boolean",
                    "default": false,
                    "description": "Include word-level timings."
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "srt",
                      "vtt",
                      "text"
                    ],
                    "default": "json",
                    "description": "json (everything), or just srt / vtt / text."
                  }
                }
              }
            },
            "audio/*": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "video/*": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript. With format=srt|vtt|text the body is that text instead of JSON. Paid responses carry PAYMENT-RESPONSE (settlement tx).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transcript"
                }
              },
              "text/vtt": {
                "schema": {
                  "type": "string"
                }
              },
              "application/x-subrip": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required: PAYMENT-REQUIRED header (x402 v2) with the exact amount for this file; JSON body includes quote {durationSec, billableMinutes, totalUsd, amount}.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "413": {
            "description": "File too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported or unreadable media",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "URL not allowed / not fetchable / not media, no audio, too long, or over maxMinutes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Speech-to-text failed (not charged)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Busy or payments misconfigured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      },
      "TranscribeRequest": {
        "type": "object",
        "description": "Exactly one of url or file.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Direct public http(s) link to an audio/video file (≤ 100 MB). Web pages / YouTube links are not supported."
          },
          "file": {
            "type": "object",
            "required": [
              "base64"
            ],
            "properties": {
              "base64": {
                "type": "string"
              },
              "filename": {
                "type": "string"
              }
            },
            "description": "Inline file (≤ 4 MB decoded)."
          },
          "diarize": {
            "type": "boolean",
            "default": true,
            "description": "Label speakers (S1, S2, ...)."
          },
          "summary": {
            "type": "boolean",
            "default": true,
            "description": "Add title, summary, key points, chapters, action items, topics."
          },
          "language": {
            "type": "string",
            "example": "en-US",
            "description": "Locale hint. Omit for automatic language detection (60 languages)."
          },
          "style": {
            "type": "string",
            "enum": [
              "clean",
              "verbatim"
            ],
            "default": "clean",
            "description": "clean removes fillers; verbatim keeps them."
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 50
            },
            "maxItems": 50,
            "description": "Names/terms to bias recognition toward."
          },
          "maxMinutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 600,
            "description": "Budget cap: refuse (422, before payment) if the audio bills more minutes."
          },
          "includeWords": {
            "type": "boolean",
            "default": false,
            "description": "Include word-level timings."
          },
          "format": {
            "type": "string",
            "enum": [
              "json",
              "srt",
              "vtt",
              "text"
            ],
            "default": "json",
            "description": "json (everything), or just srt / vtt / text."
          }
        }
      },
      "Segment": {
        "type": "object",
        "properties": {
          "speaker": {
            "type": [
              "string",
              "null"
            ]
          },
          "start": {
            "type": "number"
          },
          "end": {
            "type": "number"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "Transcript": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "durationSec": {
            "type": "number"
          },
          "language": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing": {
            "type": "object",
            "properties": {
              "billableMinutes": {
                "type": "integer"
              },
              "pricePerMinuteUsd": {
                "type": "string"
              },
              "totalUsd": {
                "type": "string"
              },
              "charged": {
                "type": "boolean"
              }
            }
          },
          "models": {
            "type": "object"
          },
          "diarization": {
            "type": "object",
            "properties": {
              "requested": {
                "type": "boolean"
              },
              "applied": {
                "type": "boolean"
              },
              "speakerCount": {
                "type": "integer"
              }
            }
          },
          "speakers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "talkTimeSec": {
                  "type": "number"
                },
                "turns": {
                  "type": "integer"
                }
              }
            }
          },
          "text": {
            "type": "string"
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Segment"
            }
          },
          "words": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "summary": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "title": {
                "type": "string"
              },
              "summary": {
                "type": "string"
              },
              "keyPoints": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "chapters": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "number"
                    },
                    "startClock": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    }
                  }
                }
              },
              "actionItems": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string"
                    },
                    "owner": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "topics": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "captions": {
            "type": "object",
            "properties": {
              "srt": {
                "type": "string"
              },
              "vtt": {
                "type": "string"
              },
              "cueCount": {
                "type": "integer"
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}