Skip to main content
Add StealthGPT humanization to your content pipeline while keeping your publishing decisions in your own workflow. These recipes turn source drafts into review files containing the original, humanized candidate, run ID, actual billing metadata, and an editorial checklist. Use them for CMS drafts, agency queues, product content, or agent-generated articles. The examples use native HTTP clients, not an SDK. They stop at review: no CMS credentials or publishing actions are included.

Choose your recipe

Both languages implement the same single and bulk modes. Pick one implementation; do not run both against the same work queue.

Prepare your drafts and API token

  1. Get your token from the Stealth API dashboard. The examples send it in the api-token header on every create and status request.
  2. Download the sample drafts and save them as review-drafts.json. Replace their text with source drafts only—no “humanize this” instructions.
  3. Give every document revision a stable, unique id, such as pricing-guide-v3. The scripts use it as the idempotency key and review filename. Keep an ID and its request settings unchanged when retrying. Use a new revision ID for deliberately changed content or a fresh attempt after a failed run.
Idempotency is scoped to your account, key and request fingerprint. Changing source text, model, quality mode, output format or preservation settings can start a new run even with the same key. After an uncertain create response, resend the original request unchanged; do not switch models or generate a new key to recover it.
Keep the token on your backend. Do not put it in browser code, a committed input file, or a CMS article.

Recipe 1: async humanization → editorial review

Copy one implementation below to review.ts or review.py. Both send rephrase: true, explicitly select model: "super", and request plain text. A run returns 202 with a runId and statusUrl; the script saves that association before polling. The scripts retry network failures, 429, and 5xx with the same body and keys, with a bounded number of attempts. Bulk mode also waits and retries 409. A terminal failed or cancelled result becomes a blocked review file; it is never silently resubmitted as a new paid run.
Save this as review.ts. It uses Node’s built-in TypeScript support and has no package dependencies.
review.ts
The result is one review-output/<document-id>.review.json per draft, plus a manifest.json mapping your IDs to API runs and a hash of each intended request. On restart, known runs are polled directly without another create call; only drafts absent from the manifest are submitted. A changed draft, model setting or callback configuration under an existing ID is rejected before submission. Run one worker per output directory; use a transactional database or job store when multiple workers share a queue. The API does not expose a caller-controlled idempotency expiry. Durable run IDs are your resume mechanism, rather than an assumption that a provider key remains valid indefinitely. If a saved run returns 404, investigate that record; these clients do not silently create a replacement.

Make review a publishing gate

Open each review file and compare sourceText with candidateText. Check names, numbers, claims and citations; test links; inspect headings, tables, lists and brand voice in the destination renderer. Then record the reviewer, time and decision in editorialReview. A downstream CMS integration should require an approved decision and the reviewed version of the text before creating a publication. The examples never set approved. They publish each completed JSON file through a temporary file and an atomic hard link, so overlapping polls and callbacks see complete reviews and keep existing editorial notes. Use a local filesystem that supports hard links. For a new paid attempt, use a new document revision ID and keep the old record.

Recipe 2: bulk humanization → collect every result → review

Use the same script and draft format with bulk:
Each request contains 1–100 items, with idempotencyKey on every item. The response’s runs[i] corresponds to items[i]; the scripts save this mapping and poll each statusUrl. They wait until the current batch is terminal before submitting the next one. Failed items are saved with editorialReview.decision: "blocked", and the scripts stop before sending another batch.
  • The platform caps the request body at 4.5 MB. These examples use a conservative 4,000,000-byte client check; long drafts may need fewer than 100 items.
  • A different batch submitted while a previous bulk batch is active can return 409. A resend covering those same active items with unchanged keys and inputs can recover the existing runs.
  • 429 or 500 can occur after keyed items were already created. Resend the same complete request; do not generate new keys for a transport retry.
  • A failed run remains failed under the same key and request. Inspect its error.code; correct the cause and deliberately choose a new revision ID for a new attempt.
See Bulk Async Runs for the account batch gate and full error contract.

Optional: signed webhooks with polling reconciliation

Set these before creating runs if you have an HTTPS callback endpoint:
The callback includes the same terminal payload as status polling. Verify HMAC over the timestamp plus raw body, confirm the run is in your manifest, then use the same review writer. A duplicate callback and a later poll converge on the same file. Never route a completed callback straight to a public CMS post. This TypeScript handler uses the review.ts functions above. Mount POST in your existing backend and give it the same durable review directory and secret as the worker. It performs local persistence only, so it can acknowledge promptly within the API’s 10-second delivery timeout. For serverless deployments, replace local files with a shared durable store; an ephemeral filesystem is not a delivery queue.
webhook.ts
Delivery is best-effort, with up to three attempts for network errors, timeouts, 429 and 5xx. Other 4xx responses stop delivery retries. Keep polling or schedule status reconciliation from the saved manifest; a missing callback does not mean the run failed. These scripts continue polling even when webhooks are enabled, making callback delivery an acceleration path rather than the only record of completion.

Billing, model controls and recovery

Humanization bills input plus output billable words, rounded up. Standard and Lite use a 1× multiplier; Super uses 2.5×. For example, 1,000 input words plus 900 output words is 1,900 plan words for Standard/Lite or 4,750 for Super. The examples store the API’s actual wordsSpent, creditsSpent, billingMode and meteredChargedCredits fields; use those values for reconciliation rather than estimating final output length. Preserved spans can affect billable word counts. Creating runs checks estimated billing access and can reserve prepaid credits. Each run is billed when it finishes. A bulk estimate is checked as a whole, and a later billing problem can still end an individual run as failed. REST calls use the API balance; MCP can follow a different account billing setting. See API pricing for current plan economics. qualityMode: "quality" is a model control, not editorial approval. Standard uses its quality-check pipeline; Super’s quality mode enables em-dash cleanup, and Lite uses its lightweight path. Choose the model for your workload and review the resulting draft. For format-sensitive content, use Text Preservation and verify the reconstructed document; selecting Markdown alone does not establish that every table, link or layout survives.

Using n8n

You can build the same review handoff with the n8n integration or HTTP Request nodes. Check your installed node version before importing a workflow: the published n8n-nodes-stealthgpt 0.1.2 schema exposes heavy and lite for humanization (heavy maps to Standard), and has no bulk operation. Use the REST contract directly for an explicit Super selection or bulk submission. Store API tokens in n8n credentials, and send results to a draft/review destination before any publish node. These examples were checked against the API source and exercised with local fixtures and mocked responses. No paid API calls or CMS publications are part of the example validation.