POST/api/v1/humanize
Rewrite a document for clarity and natural flow
Developer documentation REST API v1
Bring clearer, more natural text into your application. Choose a writing style, keep your meaning, and get a complete rewrite with transparent word-based credits.
{
"text": "Clear writing helps readers understand.",
"mode": "professional",
"strength": "medium"
}The API uses HTTPS, bearer authentication and JSON. Keep your key on your server, choose a unique idempotency key, and send the text you want to improve.
curl https://www.convertfoto.com/api/v1/humanize \
--header "Authorization: Bearer $CONVERTFOTO_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: example-document-0001" \
--data '{"text":"Clear writing helps readers understand.",
"mode":"professional","strength":"medium"}'const response = await fetch(
'https://www.convertfoto.com/api/v1/humanize',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CONVERTFOTO_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'example-document-0001'
},
body: JSON.stringify({
text: 'Clear writing helps readers understand.',
mode: 'professional',
strength: 'medium'
})
}
);
const payload = await response.json();
if (!response.ok) throw new Error(payload.error.code);
console.log(payload.data.humanized_text);$request = curl_init('https://www.convertfoto.com/api/v1/humanize');
curl_setopt_array($request, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 240,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CONVERTFOTO_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: example-document-0001',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Clear writing helps readers understand.',
'mode' => 'professional',
'strength' => 'medium',
], JSON_THROW_ON_ERROR),
]);
$body = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
if ($body === false) throw new RuntimeException('Request unconfirmed');
$payload = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if ($status !== 200) throw new RuntimeException($payload['error']['code']);
echo $payload['data']['humanized_text'];Use these examples from a trusted server. Never embed an API key in browser JavaScript, a public repository, analytics or a request URL. Replace the example idempotency value for each new document.
Create, revoke or regenerate a key in your account. Creation requires a verified active account. A key does not itself activate an API subscription or add credits. A regenerated key replaces the old key immediately.
Authorization: Bearer YOUR_PRIVATE_API_KEYKeys are shown in full once. The service stores a keyed digest and a public prefix, so a lost key must be regenerated. Revoked keys and keys invalidated by a password reset cannot authenticate. API calls use bearer credentials; they do not use website cookies.
A key has the format hz_key_<16 hex selector>_<64 hex secret>, using lowercase hexadecimal characters. Each account can hold up to ten active keys.
Send text with optional mode and strength. The default is Standard mode with Medium strength. Humanize and paraphrase requests share the same credit and complete-result guarantees.
| Parameter | Values | Purpose |
|---|---|---|
text | UTF-8 string, required | The original text. Document and plan limits apply. |
mode | standard, casual, academic, professional, creative | The writing style to preserve throughout the document. |
strength | light, medium, strong | How extensively to revise the wording. |
Every successful synchronous response contains the complete rewritten text, authoritative input/output word counts, credits used and remaining available credits. The output is plain text; treat it as untrusted text when displaying it in HTML.
{
"success": true,
"data": {
"request_id": "aabbccddeeff0011223344556677889900",
"humanized_text": "Better writing helps readers understand.",
"original_words": 5,
"rewritten_words": 5,
"word_count_version": "unicode-runs-cjk-v1"
},
"usage": {
"credits_used": 5,
"remaining_credits": 19995
}
}Paragraphs, lists, factual markers and reasonable length are validated. Review the result for meaning and accuracy before publishing. Rewriting is intended to improve clarity and tone; no AI-detector evasion is promised.
Use POST /api/v1/jobs with the same text/options and an idempotency key for asynchronous work. A queued request reserves its input-word credits before returning 202 Accepted. Poll GET /api/v1/jobs/{id} with your bearer key.
| Job status | Meaning |
|---|---|
| queued | Accepted and waiting for a worker. No partial text is available. |
| processing | The complete document is being processed sequentially. |
| succeeded | The complete result and settled credit usage are available. |
| failed | No complete result was delivered. The reservation is released. |
Poll at a modest interval and respect rate-limit headers. Queued text is encrypted and expires after 24 hours if it has not started. Completed output is available for 24 hours after completion; expired queued text or result retrieval returns 410. Scheduled cleanup removes expired ciphertext, while accounting and idempotency metadata remain.
A worker that loses its lease is not automatically restarted against the provider. Recovery reconciles a durable complete result or releases the reservation. Prompt and provider configuration are fixed when processing begins. No endpoint returns a document with failed or missing chunks.
One credit equals one input word. The server normalizes and counts text using the reported word_count_version; client counts are estimates. Rewriting the same text as a new request uses credits again.
Website and API products share one wallet, with separate product entitlements. Monthly credits expire at period end; purchased top-ups do not expire. Credits are reserved before processing and deducted only when a complete result is saved. Failed work releases its reservation, while upstream provider costs are tracked separately.
A refunded payment can place new writing on hold if its credits have already been spent. billing_refund_hold returns HTTP 402 for new work; previously completed results remain retrievable within their retention period. New top-ups may first recover that credit shortfall. Hosted checkout redirects alone do not grant credits: verified payment events update the account. Review purchases, refunds and subscriptions in Plans and credits.
Read /account and /models for the account and supported capabilities. Document, rate and concurrent-job limits depend on the configured API plan. Synchronous processing also has a deployment cap; use jobs when a document requires asynchronous processing.
| Response header | Meaning |
|---|---|
X-RateLimit-Limit | Allowed authenticated requests in the current window. |
X-RateLimit-Remaining | Requests remaining in that window. |
X-RateLimit-Reset | Window reset as a Unix timestamp in seconds. |
Retry-After | Seconds to wait after a rate-limit response or before polling a pending submission. |
Every generation or job POST requires Idempotency-Key: 16–128 characters using letters, digits, dots, underscores, colons or hyphens. Save the key with your own request record before sending it. Reuse that same key and identical text/options on the same endpoint when resolving a lost response; never switch to a fresh key simply because a request timed out. Reusing the key on a different endpoint starts a distinct billable operation.
Duplicate completed requests return the saved result without another generation or charge for 24 hours after completion. Replays remain available when new AI or queue processing is disabled, provided the API itself remains enabled. Changed content for an existing key returns a conflict. Failed or expired request identities remain closed and cannot restart processing. A timeout does not prove that the server or provider stopped working.
| HTTP status | Typical action |
|---|---|
| 400 / 422 | Correct the request shape, options or missing idempotency key. |
| 401 / 403 | Check the key, verified account and API entitlement. |
| 402 | Insufficient credits or billing_refund_hold; new processing was not admitted. Review the account balance and billing status. |
| 404 | The route or account-owned job was not found. |
| 409 | The request is still resolving, already failed, or conflicts with prior content. |
| 410 | Queued input or the temporary result has expired; the request will not run again. |
| 413 / 415 | Check document limits or use application/json. |
| 429 | Wait for the documented rate/concurrency limit. |
| 503 | Service unavailable or completion unconfirmed. Preserve the original idempotency key and check the account/job state. |
{
"success": false,
"error": {
"code": "insufficient_credits",
"message": "There are not enough available credits."
}
}All protected routes use the base path /api/v1. The list below is generated from the same registry used by the API dispatcher. The complete schemas, required headers and error responses are in the downloadable OpenAPI document.
/api/v1/humanizeRewrite a document for clarity and natural flow
/api/v1/paraphraseParaphrase a document using the same preservation rules
/api/v1/usageRead current UTC-month API usage
/api/v1/accountRead account credit balance and API entitlement
/api/v1/modelsRead public processing capabilities and document limits
/api/v1/jobsQueue a document for asynchronous processing
/api/v1/jobs/{id}Read an owned job and its complete result
Build against the contract, then verify your account limits before sending production traffic.
View OpenAPI 3.1