Developer APIv1

Humanize textwith one request.

The engine behind Study Solutions, as a REST API. Prepaid and pay as you go — $0.05 per 1,000 words.

No subscriptionFailed runs refundedBalance never expires
POST /v1/humanize
Live
$ curl www.studysolutions.app/api/v1/humanize \ -H "Authorization: Bearer $SS_API_KEY" \ -d '{"text": "AI has transformed…", "stream": true}'
{"type":"start","usage":{"input_words":412,"cost_usd":0.0206}}
{"type":"paragraph","index":1,"text":"Teachers spot gaps sooner…"}
{"type":"paragraph","index":0,"text":"AI has reshaped how we learn…"}
{"type":"paragraph","index":2,"text":"Students show up ready…"}
{"type":"done","latency_ms":3840,"balance_usd":9.9794}
Paragraphs
3/3
  • Pay as you go

    Prepaid. No plan, no minimum spend.

  • Failures are free

    Errors and timeouts refund themselves.

  • Streaming

    Paragraphs arrive as they finish.

  • Multilingual

    Replies in the language you send.

  • Never expires

    Unused balance stays yours.

  • Traceable

    A request ID on every call.

Start here

Quickstart

Create your key in the console above, export it as SS_API_KEY, and send text. The response is the humanized document plus what it cost.

curl https://www.studysolutions.app/api/v1/humanize \
  -H "Authorization: Bearer $SS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Your AI-generated text goes here."}'

Let your AI agent set it up

One click copies a setup prompt with this whole reference. Paste it into Claude Code, Cursor or Codex. View as Markdown

Keys

Authentication

Send your key as a Bearer token. x-api-key: ss_live_… also works.

Header
Authorization: Bearer ss_live_…
  • Keys start with ss_live_ and are shown once.
  • We store a SHA-256 hash, never the key.
  • One key per account. Lost it? Regenerate it.
  • Regenerating is instant: the old key fails on its next request.

Call the API from your server. A key in browser or app code can be copied by anyone who loads it.

Endpoint

Humanize

POSTwww.studysolutions.app/api/v1/humanize

Rewrites AI-generated text so it reads as human-written. Formatting — headings, lists, blank lines — is kept. The reply comes back in the language you send.

Body

textstringrequired
The text to humanize. Up to 25,000 words.
modelstring
"studysolutions". Ryne AI is coming soon — until then "ryne" returns invalid_request.default "studysolutions"
streamboolean
Stream NDJSON events as paragraphs finish. See Streaming.default false

Response

idstring
Request ID. Also in the X-Request-Id header — quote it to support.
outputstring
The humanized document.
usageobject
input_words, output_words, cost_usd.
balance_usdnumber
Balance left after this request.
latency_msnumber
Time on our side, end to end.
200 OK
{
  "id": "req_8f2c1e0b9d4a4c7f8e3b2a1d0c9e8f7a",
  "object": "humanization",
  "model": "studysolutions",
  "output": "AI has reshaped how students learn…",
  "usage": {
    "input_words": 412,
    "output_words": 405,
    "cost_usd": 0.0206
  },
  "balance_usd": 9.9794,
  "latency_ms": 3840
}

Try it

live · billed to your balance

63 words · $0.00315

Sign in to run →

Humanized text appears here.

Paragraphs stream in as each one finishes.

Optional

Streaming

With "stream": true the reply is application/x-ndjson — one JSON event per line, one paragraph event per paragraph of your document. Paragraphs are written in parallel, so they can arrive out of order; place each by its index. done carries the exact document.

startRequest accepted and charged. Carries id and usage.
progressHow many paragraphs the document has.
paragraphOne finished paragraph: index + text. Lines kept as they are (headings) come first; a revised paragraph is re-sent with the same index.
doneThe assembled output, usage, balance and latency.
errorThe run failed. Nothing is charged. Ends the stream.
Event stream
{"type":"start","id":"req_8f2c…","model":"studysolutions","usage":{"input_words":412,"cost_usd":0.0206}}
{"type":"progress","paragraphs":3}
{"type":"paragraph","index":1,"text":"…"}
{"type":"paragraph","index":0,"text":"…"}
{"type":"paragraph","index":2,"text":"…"}
{"type":"done","id":"req_8f2c…","output":"…","usage":{…,"output_words":405},"balance_usd":9.9794,"latency_ms":3840}
const res = await fetch("https://www.studysolutions.app/api/v1/humanize", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SS_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ text, stream: true }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
const paragraphs = [];
let buffer = "";

for (;;) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split("\n");
  buffer = lines.pop();
  for (const line of lines) {
    if (!line) continue;
    const event = JSON.parse(line);
    if (event.type === "paragraph") paragraphs[event.index] = event.text;
    if (event.type === "done") console.log(event.output, event.usage);
    if (event.type === "error") throw new Error(event.error.message);
  }
}

Endpoint

Balance

GETwww.studysolutions.app/api/v1/balance

Your prepaid balance, and how many words it buys at the current rate.

cURL
curl https://www.studysolutions.app/api/v1/balance \
  -H "Authorization: Bearer $SS_API_KEY"
200 OK
{
  "object": "balance",
  "balance_usd": 9.9794,
  "humanize_words_available": 199588,
  "currency": "usd"
}

Endpoint

Models

GETwww.studysolutions.app/api/v1/models

Public, no key needed. Lists the models and the price.

studysolutionsdefault

Study Solutions · $0.05 / 1K words

ryneComing soon

Ryne AI · not available over the API yet

cURL
curl https://www.studysolutions.app/api/v1/models

Reference

Errors

Every error has the same shape. Branch on error.type; messages can change.

402 Payment Required
{
  "error": {
    "type": "insufficient_balance",
    "message": "Balance is too low for this request.",
    "balance_usd": 0.0012,
    "cost_usd": 0.0206
  }
}
StatusTypeWhen
400invalid_requestBody is not JSON, `text` is missing or empty, a field has the wrong type, or the model is not available yet.
413text_too_longOver 25,000 words (or 250,000 characters) in one request.
401invalid_api_keyKey missing, malformed, unknown or revoked.
402insufficient_balanceBalance is below the cost of this request.
403account_disabledThe account is suspended or deleted.
429concurrency_limit3 requests already in flight on this account. Retry when one finishes.
502engine_errorThe engine failed mid-run. The charge is refunded.
504timeoutThe run took longer than 280 s. The charge is refunded.
503service_unavailableTemporary problem on our side. Safe to retry.

Reference

Limits & billing

$0.05 / 1,000 words

Input words, charged when the request starts. Same rate as the app.

Never charged for failures

A run that errors or times out is refunded in full, automatically.

3 requests at a time

Per account. The next one gets 429 with Retry-After — retry when one finishes.

25,000 words per request

Longer documents: split on paragraph breaks and send in parts.

Balance never expires

Top up $10–$500 at a time, by card or PayPal.

Timeouts

A run gets up to 280 s. Set your client timeout to 300 s.

Response headers

X-Request-Idstring
Same as the body id.
X-Concurrency-Limitnumber
Requests allowed in flight (3).
X-Concurrency-Remainingnumber
Free slots when this request started.
Retry-Afterseconds
On 429 only.

Benchmarks

Coming soon

Pass rates for our engine against the leading humanizers on the major AI detectors — same documents, published with the method.