{"openapi":"3.1.1","info":{"title":"ReverseGPT API","version":"1.0.0","summary":"Rewrite AI-generated text so it reads as human-written.","description":"Send a draft, get it back rewritten. One credit per word of input, up to 1000 words\nper request.\n\n**Everything is asynchronous.** `POST /humanize` answers `202` with the job envelope and a\n`Location` header; poll that URL until `job.status` is no longer `pending`, then read\n`result.humanizedText`. Runs typically finish in seconds, and the pipeline gives up after five\nminutes.\n\n**Authentication.** Send an API key from the dashboard as `Authorization: Bearer rg_live_…`\nor `x-api-key: rg_live_…`. A key carries scopes: `humanize:write` starts runs and spends\ncredits, `humanize:read` only reads them back — so an unattended poller can be given a\ncredential that cannot bill you.\n\n**Retrying safely.** Send an `Idempotency-Key` on every `POST /humanize`. A repeat of\nthe same key with the same text returns the ORIGINAL job instead of starting — and charging for\n— a second run. Keys are honoured for at least 24 hours.\n\n**Billing.** Credits are debited when a run starts, counted from the input. A run that fails is\nnot charged, and polling is always free.","termsOfService":"https://www.reversegpt.ai/terms","contact":{"name":"ReverseGPT support","url":"https://www.reversegpt.ai/contact"}},"servers":[{"url":"https://www.reversegpt.ai/api/v1","description":"Production"}],"tags":[{"name":"Humanize","description":"Start a rewrite and read it back."}],"security":[{"BearerAuth":[]},{"ApiKeyHeader":[]}],"paths":{"/humanize":{"post":{"operationId":"createHumanizeJob","summary":"Humanize text","description":"Start a run. Answers `202` with `Location` and `Retry-After`; poll that URL until\n`job.status` leaves `pending`.\n\nCosts one credit per word of `text`, at most 1000 words. Split longer\ndrafts and humanize each part.\n\nAnswers `200` instead of `202` when a replayed `Idempotency-Key` resolves to a\nrun that already finished.","tags":["Humanize"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HumanizeRequest"}}}},"responses":{"200":{"description":"A replayed idempotency key resolved to a run that has already finished.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Correlation id for this response."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the window resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"202":{"description":"The run was accepted and is in progress. `result` is null; poll `job.url`.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Correlation id for this response."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the window resets."},"Location":{"schema":{"type":"string","format":"uri"},"description":"Job status URL to poll."},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before polling."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Malformed request — unparseable JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unrecognised API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits to run the request. Nothing was queued and nothing was charged; `details` carries the required and available figures.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No job with that id belongs to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request parsed but is not runnable — empty text, more than 1000 words, or an `Idempotency-Key` reused with different text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The API key's request rate limit or quota is exhausted. See `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The humanizing queue is unreachable. Retry shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/jobs/{id}":{"get":{"operationId":"getHumanizeJob","summary":"Get a humanize job","description":"Read a run back. Free — the run was paid for when it started, and polling never costs\ncredits.\n\nRequires only `humanize:read`.","tags":["Humanize"],"security":[{"BearerAuth":[]},{"ApiKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The `job.id` returned when the run was started."}],"responses":{"200":{"description":"The job as it stands. `result` is null while `job.status` is `pending`.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Correlation id for this response."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the window resets."},"Location":{"schema":{"type":"string","format":"uri"},"description":"Job status URL to poll."},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before polling."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Malformed request — unparseable JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unrecognised API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits to run the request. Nothing was queued and nothing was charged; `details` carries the required and available figures.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No job with that id belongs to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request parsed but is not runnable — empty text, more than 1000 words, or an `Idempotency-Key` reused with different text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The API key's request rate limit or quota is exhausted. See `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The humanizing queue is unreachable. Retry shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer rg_live_…`"},"ApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"`x-api-key: rg_live_…`"}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A caller-chosen unique string. Replaying it with the same text returns the original job rather than starting a second, separately charged run. Reusing it with different text is rejected with 422."}},"schemas":{"HumanizeRequest":{"type":"object","properties":{"text":{"type":"string","minLength":1},"ultra":{"default":false,"type":"boolean"}},"required":["text"]},"Job":{"type":"object","properties":{"job":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","completed","failed"]},"url":{"type":"string","description":"Absolute URL to poll. Sent as `Location` on a 202."},"createdAt":{"type":"string"},"wordCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Words counted from the input. Credit-based plans use this many credits; Max does not debit credits."},"ultra":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Whether Ultra was enabled for this run. Null for older jobs whose mode was not recorded."}},"required":["id","status","url","createdAt","wordCount","ultra"],"additionalProperties":false},"result":{"anyOf":[{"type":"object","properties":{"humanizedText":{"type":"string","description":"The rewritten text. Return it to the user as-is."},"wordsProcessed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Words the pipeline actually rewrote."},"chunkCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many segments the text was split into."}},"required":["humanizedText","wordsProcessed","chunkCount"],"additionalProperties":false},{"type":"null"}]},"error":{"anyOf":[{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false},{"type":"null"}],"description":"Populated only when `status` is `failed`."}},"required":["job","result","error"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["type","code","message","request_id"],"properties":{"type":{"type":"string","enum":["invalid_request_error","authentication_error","permission_error","not_found_error","conflict_error","billing_error","rate_limit_error","api_error"],"description":"Coarse error class. Stable — branch on this."},"code":{"type":"string","description":"The specific machine-readable reason."},"message":{"type":"string","description":"One sentence, written as an instruction to the caller."},"details":{"description":"Structured context, when there is any."},"request_id":{"type":"string","description":"Echoed in `X-Request-Id`. Quote it to support."}}}}}}}}