{
  "openapi": "3.1.0",
  "info": {
    "title": "anex.sh batch inference API",
    "version": "1",
    "summary": "Batch inference for open models: submit a file with one prompt per row, approve a cost estimate, download one result file with a response per row.",
    "description": "The normal flow is: createInput (then upload the file to the presigned target if you did not give a source_url), createJob, poll getJob until the status is cost_ready, approveJob, poll getJob until the status is done, then getJobResult for a download link. Payment is prepaid credits; an approved job never costs more than the estimate that was approved. Prose reference: https://anex.sh/docs/api. Model ids and their exact weights: https://anex.sh/docs/api#models. Pricing: https://anex.sh/docs/pricing. An OpenAI-compatible realtime embeddings surface lives at a second server, https://api.anex.sh/realtime/v1, and takes the same API keys.",
    "termsOfService": "https://anex.sh/terms",
    "contact": {
      "name": "anex.sh support",
      "email": "support@anex.sh",
      "url": "https://anex.sh/support"
    }
  },
  "servers": [
    {
      "url": "https://api.anex.sh/batch/v1",
      "description": "Batch API"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "inputs",
      "description": "Getting an input file into storage."
    },
    {
      "name": "jobs",
      "description": "Submitting, approving, cancelling and downloading batch jobs."
    },
    {
      "name": "realtime",
      "description": "Single-request embeddings, OpenAI-compatible, at https://api.anex.sh/realtime/v1."
    }
  ],
  "externalDocs": {
    "description": "API reference (prose)",
    "url": "https://anex.sh/docs/api"
  },
  "paths": {
    "/inputs": {
      "post": {
        "operationId": "createInput",
        "tags": [
          "inputs"
        ],
        "summary": "Create an input: ingest a file from an HTTPS URL, or get a presigned target to upload one directly",
        "description": "With source_url, the API copies the file into storage from that URL (a presigned GET on your own bucket is the simplest source) and the response's status goes pending, copying, ready (or failed with an error). Without source_url the response is instead a presigned S3 POST target: send every entry of `fields` as a form field and the file itself as the `file` field, last, before expires_at; format is then required. Requires a positive credit balance (402 otherwise). Keep the returned id: it is the input_id for createJob, which settles a just-finished upload itself, so no poll is needed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInputRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The input was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Input"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed: a non-HTTPS URL, a missing format on a direct upload, or a callback_url in upload mode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "The organization's credit balance is zero or below.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The source advertises a size over the input cap.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/inputs/{id}": {
      "get": {
        "operationId": "getInput",
        "tags": [
          "inputs"
        ],
        "summary": "Get an input's status",
        "description": "Poll until status is ready (or failed, with an error). A direct upload reports awaiting_upload until the object lands. An id of another organization answers 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The input id returned by createInput.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The input's current state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Input"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such input in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs": {
      "post": {
        "operationId": "createJob",
        "tags": [
          "jobs"
        ],
        "summary": "Submit a job: an input plus a model",
        "description": "Validates the whole input (format, size, row count, inline media, response_format) before the job exists, then returns it in status submitted. The job is then estimated (status estimating) and waits at cost_ready for approveJob, unless the organization has auto-approve on. Give exactly one of input_id and input_s3_uri. Model ids: https://anex.sh/docs/api#models.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateJobRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The job was created (status submitted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "400": {
            "description": "The request or the input file failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such input in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The input is not ready yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "An unknown model, or a field that does not apply to the model (for example max_output_tokens on an embedding model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many jobs awaiting approval in this organization; approve or cancel some first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "tags": [
          "jobs"
        ],
        "summary": "Poll a job for its status, estimate and row counts",
        "description": "status moves submitted, estimating, cost_ready, approved, in_progress, merging, done; or ends failed / cancelled. At cost_ready the estimate fields are set: est_cost_cents is the amount held on approval and the cost ceiling. Row counts roll up as rows finish. data_expires_at is when the job's data is deleted; the record itself stays queryable.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The job id returned by createJob.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job's current state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such job in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}/approve": {
      "post": {
        "operationId": "approveJob",
        "tags": [
          "jobs"
        ],
        "summary": "Approve a job's estimate, which starts paid GPU work",
        "description": "Holds est_cost_cents against the prepaid balance. The job must be in cost_ready; a job left there for 24 hours is cancelled automatically, free of charge. With auto-approve on for the organization this call is made for you.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The job id returned by createJob.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approved: status is now approved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "The balance does not cover the estimate; add credits and approve again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such job in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The job is not awaiting approval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}/cancel": {
      "post": {
        "operationId": "cancelJob",
        "tags": [
          "jobs"
        ],
        "summary": "Cancel a job",
        "description": "A job with no work in flight stops at once (status cancelled, nothing billed). A job that has started answers cancelling: no new work starts, rows already running finish, and the job settles as cancelled with the completed rows downloadable as a partial result and billed. A job that is estimating, merging or already terminal answers 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The job id returned by createJob.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "status is cancelled or cancelling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such job in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Too early (estimating) or too late (merging or terminal) to cancel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}/result": {
      "get": {
        "operationId": "getJobResult",
        "tags": [
          "jobs"
        ],
        "summary": "Get a presigned download link for the result file",
        "description": "Available for a done job, and for a failed or cancelled job that delivered the rows it had finished (partial true). result_url is valid for expires_in seconds; call again for a fresh link. The file's contents are described at https://anex.sh/docs/output. Results are deleted 30 days after the job finishes, or earlier through deleteJobData; 410 afterwards.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The job id returned by createJob.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A download link.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobResult"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such job in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "No result exists yet (the job is not finished, or finished with nothing to deliver).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "The result has been deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}/data": {
      "delete": {
        "operationId": "deleteJobData",
        "tags": [
          "jobs"
        ],
        "summary": "Delete a finished job's input and result data now",
        "description": "Removes the job's input file, result file and every intermediate object immediately, instead of at the 30-day retention mark. The job record (statuses, counts, cost) stays; getJob then reports data_deleted_at and getJobResult answers 410. Only a finished job (done, failed, cancelled) qualifies: 409 otherwise, cancel it first. Idempotent: repeating it answers 200 with the original data_deleted_at. Download the result before calling this; nothing can bring the data back.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The job id returned by createJob.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The data is gone (now, or earlier).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDataDeletion"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such job in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The job has not finished yet; cancel it first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/models": {
      "servers": [
        {
          "url": "https://api.anex.sh/realtime/v1",
          "description": "Realtime API"
        }
      ],
      "get": {
        "operationId": "listRealtimeModels",
        "tags": [
          "realtime"
        ],
        "summary": "List the models served by the realtime embeddings API",
        "description": "OpenAI-compatible; served at https://api.anex.sh/realtime/v1/models. The batch API has no list-models endpoint: its model ids are at https://anex.sh/docs/api#models.",
        "responses": {
          "200": {
            "description": "The realtime models.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/embeddings": {
      "servers": [
        {
          "url": "https://api.anex.sh/realtime/v1",
          "description": "Realtime API"
        }
      ],
      "post": {
        "operationId": "createEmbedding",
        "tags": [
          "realtime"
        ],
        "summary": "Embed one text or a short list of texts, at request time",
        "description": "OpenAI-compatible; served at https://api.anex.sh/realtime/v1/embeddings and usable through the OpenAI SDK with that base_url. Text only (embed images and video with a batch job on the same model; the vectors share one space). At most 128 inputs, 262,144 characters per input and 2,097,152 across the request. Vectors are last-token pooled and L2 normalized; no instruction or chat template is added to your text.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmbeddingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The vectors, one per input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddingResponse"
                }
              }
            }
          },
          "400": {
            "description": "Too many inputs, an input too long, non-text content, or an encoding_format other than float.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is invalid or no longer active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "The organization's credit balance is zero or below.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The realtime API is frozen or billing is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key from the console's Keys page (https://anex.sh/docs/console#keys), sent as 'Authorization: Bearer <api-key>'. Keys belong to the organization, not to a person."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Every error response carries detail; the error object adds a stable code and a hint.",
        "properties": {
          "detail": {
            "type": "string",
            "description": "What went wrong."
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "A stable machine-readable code (not_found, conflict, payment_required, ...)."
              },
              "status": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string",
                "description": "What to do about it."
              }
            }
          }
        },
        "required": [
          "detail"
        ]
      },
      "CreateInputRequest": {
        "type": "object",
        "properties": {
          "source_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL to copy the input file from. Omit it to get a presigned upload target instead."
          },
          "format": {
            "type": "string",
            "enum": [
              "jsonl",
              "parquet"
            ],
            "description": "The input file's format. Optional with source_url (inferred from its extension), required for a direct upload."
          },
          "callback_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS endpoint to notify (input.ready / input.failed) when the copy finishes. source_url mode only."
          }
        }
      },
      "Input": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "copying",
              "ready",
              "failed",
              "awaiting_upload"
            ]
          },
          "input_s3_uri": {
            "type": "string",
            "description": "Where the file lives in storage; accepted by createJob in place of input_id."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the copy failed, when status is failed."
          },
          "callback_secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "HMAC secret for verifying the callback; returned once, on create, only with a callback_url."
          },
          "upload_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Direct upload only: the presigned POST target."
          },
          "fields": {
            "type": [
              "object",
              "null"
            ],
            "description": "Direct upload only: the form fields to send with the file, returned only on create.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Direct upload only: the upload must start before this time."
          }
        },
        "required": [
          "id",
          "status",
          "input_s3_uri"
        ]
      },
      "CreateJobRequest": {
        "type": "object",
        "properties": {
          "input_id": {
            "type": "string",
            "format": "uuid",
            "description": "An input from createInput. Give exactly one of input_id and input_s3_uri."
          },
          "input_s3_uri": {
            "type": "string",
            "description": "The input_s3_uri of an input, instead of its id."
          },
          "model": {
            "type": "string",
            "description": "A model id from https://anex.sh/docs/api#models."
          },
          "instruction_column": {
            "type": "string",
            "description": "Parquet inputs on a chat model: the column holding each row's prompt. Required for parquet, ignored for JSONL."
          },
          "max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768,
            "description": "Per-row output cap. Omit it and the cap is estimated from a sample of the rows (the default); set it to fix the cap and the price basis yourself."
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768,
            "deprecated": true,
            "description": "Former name of max_output_tokens; still accepted. Give one of the two."
          },
          "reasoning": {
            "type": "boolean",
            "description": "Job-level thinking default on a reasoning model. Omit for the model's own default; true on a model with no reasoning trace is refused (422)."
          },
          "reasoning_budget": {
            "type": "integer",
            "minimum": 0,
            "maximum": 32768,
            "description": "Cap on thinking tokens per row on a reasoning model. Omit = estimated, 0 = no cap. Counts inside max_output_tokens."
          },
          "response_format": {
            "type": "object",
            "description": "Applied to every row: {\"type\":\"json_object\"} or {\"type\":\"json_schema\",\"json_schema\":{...}}. See https://anex.sh/docs/output#structured-output."
          },
          "input_column": {
            "type": "string",
            "description": "Embedding models, parquet inputs: the column whose text is embedded. Required for parquet."
          },
          "dimensions": {
            "type": "integer",
            "minimum": 32,
            "description": "Embedding models: truncate the output vectors to this width (Matryoshka). Omit for the model's full width."
          }
        },
        "required": [
          "model"
        ]
      },
      "Job": {
        "type": "object",
        "description": "createJob, approveJob and cancelJob return only id and status; getJob returns every field.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "submitted",
              "estimating",
              "cost_ready",
              "approved",
              "in_progress",
              "cancelling",
              "merging",
              "done",
              "failed",
              "cancelled"
            ]
          },
          "est_input_tok": {
            "type": [
              "integer",
              "null"
            ]
          },
          "est_output_tok": {
            "type": [
              "integer",
              "null"
            ]
          },
          "est_cost_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The approval hold and the cost ceiling, in cents. Set at cost_ready."
          },
          "est_processing_seconds": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The expected wall-clock time to completion once approved."
          },
          "success_rows": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error_rows": {
            "type": [
              "integer",
              "null"
            ]
          },
          "format_error_rows": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rows whose response_format could not be satisfied."
          },
          "truncated_rows": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rows cut off at max_output_tokens."
          },
          "pending_rows": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "approved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "data_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the job's data is deleted; null until the job is terminal."
          },
          "data_deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the data was actually deleted (retention, or deleteJobData); null while it still exists."
          },
          "partial": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "True on a failed or cancelled job that still delivered the rows it finished."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "invalid_input",
              "internal_error",
              null
            ]
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "max_output_tokens": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The effective per-row output cap (yours, or the estimate)."
          },
          "max_tokens": {
            "type": [
              "integer",
              "null"
            ],
            "deprecated": true,
            "description": "Former name of max_output_tokens, echoed alongside it."
          },
          "reasoning_budget": {
            "type": [
              "integer",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "reasoning": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "task_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "chat",
              "embed",
              null
            ]
          },
          "format": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "jsonl",
              "parquet",
              null
            ]
          },
          "instruction_column": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_format": {
            "type": [
              "object",
              "null"
            ]
          },
          "dimensions": {
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "JobDataDeletion": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "submitted",
              "estimating",
              "cost_ready",
              "approved",
              "in_progress",
              "cancelling",
              "merging",
              "done",
              "failed",
              "cancelled"
            ]
          },
          "data_deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "JobResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "submitted",
              "estimating",
              "cost_ready",
              "approved",
              "in_progress",
              "cancelling",
              "merging",
              "done",
              "failed",
              "cancelled"
            ]
          },
          "result_url": {
            "type": "string",
            "format": "uri",
            "description": "Presigned GET link to the result file."
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds the link stays valid."
          },
          "partial": {
            "type": "boolean"
          },
          "row_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rows actually in the file."
          }
        },
        "required": [
          "id",
          "status",
          "result_url",
          "expires_in"
        ]
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "object": {
                  "type": "string",
                  "const": "model"
                },
                "owned_by": {
                  "type": "string"
                }
              },
              "required": [
                "id"
              ]
            }
          }
        }
      },
      "EmbeddingRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "A realtime model id from listRealtimeModels."
          },
          "input": {
            "description": "One text, or up to 128 texts.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "maxItems": 128,
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "dimensions": {
            "type": "integer",
            "minimum": 32,
            "description": "Truncate the vectors to this width; the range depends on the model."
          },
          "encoding_format": {
            "type": "string",
            "enum": [
              "float"
            ]
          }
        },
        "required": [
          "model",
          "input"
        ]
      },
      "EmbeddingResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "model": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "type": "string",
                  "const": "embedding"
                },
                "index": {
                  "type": "integer"
                },
                "embedding": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          }
        }
      }
    }
  }
}
