{
  "components": {
    "schemas": {
      "ContentScreeningResult": {
        "properties": {
          "flags": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "recommendation": {
            "enum": [
              "approve",
              "review",
              "reject"
            ],
            "type": "string"
          },
          "riskLevel": {
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "type": "string"
          },
          "safe": {
            "type": "boolean"
          },
          "summary": {
            "type": "string"
          },
          "adPlacement": {
            "type": "object",
            "properties": {
              "suitable": {
                "type": "boolean"
              },
              "riskLevel": {
                "type": "string",
                "enum": [
                  "low",
                  "medium",
                  "high"
                ]
              },
              "categories": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "blocklistMatches": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "notes": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "safe",
          "riskLevel",
          "summary",
          "recommendation",
          "adPlacement"
        ],
        "type": "object"
      },
      "CreatorBriefResult": {
        "properties": {
          "angle": {
            "type": "string"
          },
          "cta": {
            "type": "string"
          },
          "hook": {
            "type": "string"
          },
          "keyMoments": {
            "items": {
              "properties": {
                "note": {
                  "type": "string"
                },
                "timestamp": {
                  "type": "string"
                }
              },
              "required": [
                "note"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "summary": {
            "type": "string"
          },
          "transcriptExcerpt": {
            "type": "string"
          },
          "vetting": {
            "type": "object",
            "properties": {
              "contentThemes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "tone": {
                "type": "string"
              },
              "audienceFit": {
                "type": "string"
              },
              "brandRiskFlags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "partnershipRecommendation": {
                "type": "string",
                "enum": [
                  "approve",
                  "review",
                  "reject"
                ]
              }
            }
          }
        },
        "required": [
          "hook",
          "angle",
          "summary",
          "vetting"
        ],
        "type": "object"
      },
      "Error": {
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "Job": {
        "properties": {
          "error": {
            "type": "string"
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string"
          },
          "jobId": {
            "format": "uuid",
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/VideoAnalysis"
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "video": {
            "format": "uri",
            "type": "string"
          },
          "videoId": {
            "type": "string"
          }
        },
        "required": [
          "jobId",
          "videoId",
          "status",
          "video",
          "expiresAt"
        ],
        "type": "object"
      },
      "JobStatus": {
        "enum": [
          "pending",
          "processing",
          "success",
          "failed"
        ],
        "type": "string"
      },
      "OutputFormat": {
        "description": "Workflow output template. Omit for default VideoAnalysis. Caches are isolated per format.",
        "enum": [
          "content-screening",
          "creator-brief",
          "recipe",
          "tutorial-guide",
          "quote-highlights",
          "product-tagging",
          "shop-the-look",
          "review-summary",
          "workout-plan",
          "health-claims",
          "flashcards",
          "curriculum-tags",
          "language-learning",
          "ugc-verification",
          "breaking-news-signal",
          "eyewitness-timeline",
          "song-context",
          "lyric-hook",
          "sound-trend",
          "technique-analysis",
          "highlight-reel",
          "scouting-report",
          "destination-guide",
          "restaurant-discovery"
        ],
        "type": "string"
      },
      "PaymentOption": {
        "properties": {
          "description": {
            "type": "string"
          },
          "maxAmountRequired": {
            "example": "$0.10",
            "type": "string"
          },
          "mimeType": {
            "example": "application/json",
            "type": "string"
          },
          "network": {
            "example": "eip155:8453",
            "type": "string"
          },
          "payTo": {
            "description": "Recipient address.",
            "type": "string"
          },
          "resource": {
            "example": "POST /v1/jobs",
            "type": "string"
          },
          "scheme": {
            "example": "exact",
            "type": "string"
          }
        },
        "required": [
          "scheme",
          "network",
          "resource",
          "payTo",
          "maxAmountRequired"
        ],
        "type": "object"
      },
      "PaymentRequiredResponse": {
        "description": "x402 PaymentRequiredResponse. See https://x402.org for the full schema.",
        "properties": {
          "accepts": {
            "items": {
              "$ref": "#/components/schemas/PaymentOption"
            },
            "type": "array"
          },
          "x402Version": {
            "example": 1,
            "type": "integer"
          }
        },
        "required": [
          "x402Version",
          "accepts"
        ],
        "type": "object"
      },
      "PollJobResponse": {
        "properties": {
          "error": {
            "description": "Present when status is failed.",
            "type": "string"
          },
          "format": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OutputFormat"
              }
            ],
            "description": "Optional workflow output template. Omit for default VideoAnalysis (transcript, scenes, visual summary). When set, `result` uses the matching workflow shape and responses echo this field."
          },
          "jobId": {
            "format": "uuid",
            "type": "string"
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/VideoAnalysis"
              },
              {
                "$ref": "#/components/schemas/ContentScreeningResult"
              },
              {
                "$ref": "#/components/schemas/CreatorBriefResult"
              },
              {
                "$ref": "#/components/schemas/RecipeResult"
              },
              {
                "$ref": "#/components/schemas/WorkflowFormatResult"
              }
            ],
            "description": "VideoAnalysis when format is omitted. ContentScreeningResult / CreatorBriefResult / RecipeResult when those formats are set. WorkflowFormatResult (open shape) for the other 21 workflow formats."
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "videoId": {
            "type": "string"
          }
        },
        "required": [
          "jobId",
          "videoId",
          "status"
        ],
        "type": "object"
      },
      "RecipeIngredient": {
        "properties": {
          "amount": {
            "type": [
              "string",
              "null"
            ]
          },
          "item": {
            "type": "string"
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "item"
        ],
        "type": "object"
      },
      "RecipeInstruction": {
        "properties": {
          "step": {
            "type": "integer"
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "step",
          "text"
        ],
        "type": "object"
      },
      "RecipeMetadata": {
        "properties": {
          "cookTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "cookingMethod": {
            "type": [
              "string",
              "null"
            ]
          },
          "cuisine": {
            "type": [
              "string",
              "null"
            ]
          },
          "dietaryPreferences": {
            "type": [
              "string",
              "null"
            ]
          },
          "dishType": {
            "type": [
              "string",
              "null"
            ]
          },
          "isQuickAndEasy": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "mealType": {
            "type": [
              "string",
              "null"
            ]
          },
          "prepTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "temperature": {
            "$ref": "#/components/schemas/RecipeTemperature"
          },
          "yield": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "temperature"
        ],
        "type": "object"
      },
      "RecipeResult": {
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "ingredients": {
            "items": {
              "$ref": "#/components/schemas/RecipeIngredient"
            },
            "type": "array"
          },
          "instructions": {
            "items": {
              "$ref": "#/components/schemas/RecipeInstruction"
            },
            "type": "array"
          },
          "metadata": {
            "$ref": "#/components/schemas/RecipeMetadata"
          },
          "title": {
            "type": "string"
          }
        },
        "required": [
          "title",
          "error",
          "ingredients",
          "instructions",
          "metadata"
        ],
        "type": "object"
      },
      "RecipeTemperature": {
        "properties": {
          "fanAdjusted": {
            "type": "boolean"
          },
          "unit": {
            "enum": [
              "C",
              "F"
            ],
            "type": "string"
          },
          "value": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "unit",
          "fanAdjusted"
        ],
        "type": "object"
      },
      "Scene": {
        "properties": {
          "description": {
            "type": "string"
          },
          "timestamp": {
            "description": "Scene start time (e.g. 0:08).",
            "type": "string"
          }
        },
        "required": [
          "description"
        ],
        "type": "object"
      },
      "SubmitJobRequest": {
        "properties": {
          "format": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OutputFormat"
              }
            ],
            "description": "Optional workflow output template. Omit for default VideoAnalysis (transcript, scenes, visual summary). When set, `result` uses the matching workflow shape and responses echo this field."
          },
          "url": {
            "description": "TikTok, Instagram Reel, or YouTube Shorts URL.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "SubmitJobResponse": {
        "description": "Either a pending job (with pollUrl) or a completed cache hit (with result).",
        "properties": {
          "format": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OutputFormat"
              }
            ],
            "description": "Optional workflow output template. Omit for default VideoAnalysis (transcript, scenes, visual summary). When set, `result` uses the matching workflow shape and responses echo this field."
          },
          "jobId": {
            "format": "uuid",
            "type": "string"
          },
          "pollUrl": {
            "description": "Relative URL to poll for status. Present on new jobs (HTTP 202) when status is pending.",
            "type": "string"
          },
          "result": {
            "description": "VideoAnalysis when format is omitted. ContentScreeningResult / CreatorBriefResult / RecipeResult when those formats are set. WorkflowFormatResult (open shape) for the other 21 workflow formats.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VideoAnalysis"
              },
              {
                "$ref": "#/components/schemas/ContentScreeningResult"
              },
              {
                "$ref": "#/components/schemas/CreatorBriefResult"
              },
              {
                "$ref": "#/components/schemas/RecipeResult"
              },
              {
                "$ref": "#/components/schemas/WorkflowFormatResult"
              }
            ]
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "videoId": {
            "type": "string"
          }
        },
        "required": [
          "jobId",
          "videoId",
          "status"
        ],
        "type": "object"
      },
      "VideoAnalysis": {
        "properties": {
          "author": {
            "type": "string"
          },
          "authorHandle": {
            "type": "string"
          },
          "language": {
            "description": "ISO 639-1 language code.",
            "type": "string"
          },
          "onScreenText": {
            "type": "string"
          },
          "platform": {
            "enum": [
              "tiktok",
              "instagram",
              "youtube"
            ],
            "type": "string"
          },
          "processedAt": {
            "format": "date-time",
            "type": "string"
          },
          "scenes": {
            "items": {
              "$ref": "#/components/schemas/Scene"
            },
            "type": "array"
          },
          "title": {
            "type": "string"
          },
          "transcription": {
            "type": "string"
          },
          "url": {
            "format": "uri",
            "type": "string"
          },
          "visualDescription": {
            "type": "string"
          }
        },
        "required": [
          "platform",
          "url",
          "transcription",
          "visualDescription",
          "processedAt"
        ],
        "type": "object"
      },
      "WorkflowFormatResult": {
        "type": "object",
        "description": "Workflow output JSON. Exact fields depend on the requested format. See https://entit.ai/docs/api#workflow-formats",
        "additionalProperties": true
      }
    }
  },
  "info": {
    "contact": {
      "name": "entit.ai",
      "url": "https://entit.ai"
    },
    "description": "Async job model. POST /v1/jobs is paid via x402 ($0.10 USDC on Base or Solana mainnet). Omit `format` for default VideoAnalysis (transcript, scenes, visual summary). Optional `format` selects one of 24 workflow templates — see https://entit.ai/docs/api#workflow-formats. GET /v1/jobs/{jobId} is free; clients should honor the Retry-After response header. See https://entit.ai/docs for full documentation.",
    "license": {
      "name": "Proprietary",
      "url": "https://entit.ai/terms"
    },
    "summary": "Structured analysis for short-form video (TikTok, Instagram Reels, YouTube Shorts).",
    "title": "entit.ai API",
    "version": "1.0.0",
    "x-guidance": "Paid: POST /v1/jobs with x402 ($0.10 USDC on Base or Solana). Send X-Payment on submit; poll GET /v1/jobs/{jobId} for free. Default (omit format): full VideoAnalysis. Optional format: one of 24 workflow templates (creator-brief, content-screening, recipe, …) — https://entit.ai/docs/api#workflow-formats. Docs: https://entit.ai/docs/api"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/jobs": {
      "post": {
        "description": "Submit a TikTok, Instagram Reel, or YouTube Shorts URL. Requires an x402 payment header on the first request. Omit `format` for default VideoAnalysis. Optional `format` selects a workflow template (24 slugs — creator-brief, content-screening, recipe, …; see https://entit.ai/docs/api#workflow-formats). Caches are per format. New jobs return 202 with a jobId and pollUrl; cached repeat lookups return 200 immediately with status: success and the full analysis inline in result.",
        "operationId": "submitJob",
        "parameters": [
          {
            "description": "Video URL. Alternative to JSON body.",
            "in": "query",
            "name": "url",
            "required": false,
            "schema": {
              "format": "uri",
              "type": "string"
            }
          },
          {
            "description": "x402 payment header. If absent or invalid, the server responds 402 Payment Required with the accept schema.",
            "in": "header",
            "name": "X-Payment",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "defaultVideoAnalysis": {
                  "summary": "Default — omit format for full VideoAnalysis",
                  "value": {
                    "url": "https://www.tiktok.com/@creator/video/1234567890"
                  }
                },
                "creatorBrief": {
                  "summary": "Optional workflow format (typed result shape)",
                  "value": {
                    "format": "creator-brief",
                    "url": "https://www.tiktok.com/@creator/video/1234567890"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/SubmitJobRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "cached": {
                    "summary": "Cached job (status: success with inline result)",
                    "value": {
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "result": {
                        "platform": "tiktok",
                        "processedAt": "2026-05-20T12:34:56Z",
                        "transcription": "...",
                        "url": "https://www.tiktok.com/@janecreates/video/7123456789",
                        "visualDescription": "..."
                      },
                      "status": "success",
                      "videoId": "7123456789"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SubmitJobResponse"
                }
              }
            },
            "description": "Cache hit. The video has already been analyzed; the full result is returned inline and the caller does not need to poll."
          },
          "202": {
            "content": {
              "application/json": {
                "examples": {
                  "new": {
                    "summary": "New job (pending)",
                    "value": {
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "pollUrl": "/v1/jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "status": "pending",
                      "videoId": "7123456789"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SubmitJobResponse"
                }
              }
            },
            "description": "New job accepted. Poll pollUrl until status is success or failed."
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "badUrl": {
                    "value": {
                      "error": "Error resolving url: currently we only support tiktok, instagram and youtube shorts urls"
                    }
                  },
                  "noUrl": {
                    "value": {
                      "error": "No url provided"
                    }
                  },
                  "photo": {
                    "value": {
                      "error": "TikTok slideshow conversion is not supported"
                    }
                  },
                  "videoId": {
                    "value": {
                      "error": "Error getting video ID"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Invalid request (missing url, unsupported platform, photo/slideshow URL, etc.)."
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRequiredResponse"
                }
              }
            },
            "description": "Payment Required. Body is the x402 PaymentRequiredResponse."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Internal server error."
          }
        },
        "security": [],
        "summary": "Submit a video URL for analysis",
        "tags": [
          "jobs"
        ],
        "x-payment-info": {
          "price": {
            "amount": "0.10",
            "currency": "USD",
            "mode": "fixed"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        }
      }
    },
    "/v1/jobs/{jobId}": {
      "get": {
        "description": "Free endpoint. Returns Retry-After: 5 while status is pending or processing.",
        "operationId": "pollJob",
        "parameters": [
          {
            "in": "path",
            "name": "jobId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "failed": {
                    "value": {
                      "error": "video download timed out",
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "status": "failed",
                      "videoId": "7123456789"
                    }
                  },
                  "pending": {
                    "value": {
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "status": "pending",
                      "videoId": "7123456789"
                    }
                  },
                  "processing": {
                    "value": {
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "status": "processing",
                      "videoId": "7123456789"
                    }
                  },
                  "success": {
                    "value": {
                      "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "result": {
                        "platform": "tiktok",
                        "processedAt": "2026-05-20T12:34:56Z",
                        "transcription": "...",
                        "url": "https://www.tiktok.com/@janecreates/video/7123456789",
                        "visualDescription": "..."
                      },
                      "status": "success",
                      "videoId": "7123456789"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PollJobResponse"
                }
              }
            },
            "description": "Job exists.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before next poll. Present while pending/processing.",
                "schema": {
                  "example": 5,
                  "type": "integer"
                }
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Job not found"
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unknown jobId."
          },
          "410": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Job expired"
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Job expired (ExpiresAt elapsed; 24h TTL)."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Internal server error."
          }
        },
        "security": [],
        "summary": "Poll job status",
        "tags": [
          "jobs"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production",
      "url": "https://api.entit.ai"
    }
  ],
  "tags": [
    {
      "description": "Submit and poll video analysis jobs.",
      "name": "jobs"
    }
  ],
  "x-discovery": {
    "ownershipProofs": [
      "0x4d4864fc495963690561c53289Ae7eD7cFd4aAB0"
    ]
  }
}
