Integrate Text Detection
Authenticate with an API key, submit text and handle the result in your application.
Open Developer DashboardMake Your First Request
- Create an AIScan account and verify your email.
- Add prepaid funds in your Developer Dashboard.
- Create a key in your Developer Dashboard and save it on your server.
# Save one ID per job; reuse it when retrying this curl command.
AISCAN_REQUEST_ID="$(uuidgen)"
curl --fail-with-body 'https://app.aiscan.app/api/v1/detect/text' \
-H "Authorization: Bearer $AISCAN_API_KEY" \
-H "Idempotency-Key: $AISCAN_REQUEST_ID" \
-H "Content-Type: application/json" \
-d '{"text":"Paste at least fifty characters of the text you want to check here."}'Set AISCAN_API_KEY on your server. Keep the full key out of browser code. Include an Idempotency-Key for each job and reuse it with identical text on retries. A replay uses the original result without another charge.
Example Response
{
"id": "request-id",
"result": {
"aiScore": 24,
"isHuman": true,
"feedback": "Likely human-written",
"wordCount": 13,
"aiWordCount": 0,
"highlighted": []
},
"usage": {
"currency": "usd",
"words": 13,
"cost_micros": 488,
"balance_micros": 24999512,
"rate_version": "words-2026-10-06"
}
}Example values are illustrative. Text scores use a 0–100 scale; detection is an estimate, not proof of authorship.
Use usage.words and usage.cost_micros for billing. The legacy usage.units field is retained for compatibility and no longer determines the charge. Saved retries retain their original rate and charge.
Text Detection
POST/api/v1/detect/text
{"text":"Your text, between 50 and 20,000 characters"}Returns an AI score, word counts, and flagged passages when available.
Prepaid Usage and Limits
| Operation | Cost | Maximum |
|---|---|---|
| Text Detection | $3.75 USD per 100,000 words | 20,000 characters |
Text detection uses Suedo. Words are separated by whitespace. Each request is charged for its actual word count at $3.75 per 100,000 words. A 1,000-word request costs $0.0375; 2,000 words cost $0.075. There is no block minimum. Each request's cost rounds up to the next $0.000001 for accounting precision.
Add $25, $50, or $100 USD through Stripe. Funds become available only after payment is confirmed. There is no monthly subscription, monthly reset, or automatic top-up. Requests stop when the available balance is too low. Refunds and payment disputes adjust the available balance.
All keys share an account-wide limit of 60 requests per minute. Web tools and API calls also share an account limit of eight simultaneous provider calls. Temporary service capacity limits can return 429; follow the Retry-After header. Failed requests release reserved funds. Interrupted requests become eligible for release after 15 minutes; opening the dashboard, making another request or scheduled cleanup reconciles them. Balance values are snapshots and may change during concurrent requests. The public API currently supports text detection. Image detection and Humanizer are available in the Pro web tools.
Keep API keys on your server. Keys expire after one year and can be revoked in the dashboard. Submitted text is not shown in API usage history.
Retry Without Paying Twice
Every paid request requires an Idempotency-Key header: a unique job ID of 8–128 letters, numbers, periods, underscores, colons or hyphens. Save it before sending your request. Reuse the same key and identical text after a timeout or lost response, including when switching API keys within the same account.
Completed responses, including terminal errors, are available for replay for 24 hours. Replays include Idempotency-Replayed: true, return the original balance snapshot, and make no new provider call or charge. The response may contain flagged text passages; its cached content is erased by hourly cleanup after the replay window.
A 409 request_in_progress means wait for Retry-After and retry the same key. A key used with different text returns idempotency_conflict. If an interrupted outcome cannot be recovered, reserved funds are released after 15 minutes and request_outcome_unknown prevents that key running again. Expired responses return 410 idempotency_result_expired. We keep the key fingerprint with the billing record so an old retry never becomes a new charge. Use a new key only when you deliberately want to submit a new job.
Handle Errors
Errors include an HTTP status and error.code, error.message, and error.request_id. Successful responses include X-Balance-Micros and X-Request-Id.
| Status | Meaning | Next Step |
|---|---|---|
| 400 / 413 / 415 | Invalid input | Check JSON, text length, and content type. |
| 401 | Invalid or expired key | Use an active key from your dashboard. |
| 402 | Insufficient prepaid balance | Add funds in the Developer dashboard. |
| 409 | Retry key conflict or request pending | Read error.code; pending requests can retry the same key after Retry-After. |
| 410 | Stored response expired | This key will not run again. Use a new key only for a new job. |
| 429 | Rate or capacity limit | Follow Retry-After. Do not retry completed bulk documents. |
| 502 / 503 | Service unavailable | Retry with exponential backoff. |
If a response is lost, retry with the same Idempotency-Key and identical text to avoid a second charge.