Processing articles one at a time is fine when you have ten posts to humanize. When you have ten thousand, it’s a bottleneck. Every individual API call carries overhead: connection setup, authentication, response parsing. Multiply that by 10,000 and you’re looking at hours of unnecessary wait time.
The Humanizer API’s batch endpoint solves this. Instead of one text per request, you send arrays of up to 100 texts and get back humanized versions in a single response. Here’s how to use it at production scale.
Batch Endpoint Basics
The batch endpoint accepts an array of texts and returns an array of humanized results in the same order. The request format is straightforward:
POST /v1/humanize/batch
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"texts": [
"First article content here...",
"Second article content here...",
"Third article content here..."
],
"tone": "professional"
}
The response mirrors the request structure:
{
"results": [
{
"humanized_text": "First article, now naturally written...",
"confidence_score": 0.94,
"word_count": 1250
},
{
"humanized_text": "Second article, humanized and ready...",
"confidence_score": 0.91,
"word_count": 980
}
],
"total_words_processed": 3580,
"processing_time_ms": 2840
}
Each result includes the humanized text, a confidence score indicating how natural it reads, and the word count. The total_words_processed field tracks your API quota usage.
Chunking Your Dataset
With a 100-text limit per batch request, processing 10,000 articles means 100 batch calls. The chunking logic is simple:
import requests
import json
def chunk_list(data, size=100):
for i in range(0, len(data), size):
yield data[i:i + size]
articles = load_articles() # Your 10,000 articles
api_key = "YOUR_API_KEY"
results = []
for batch_num, chunk in enumerate(chunk_list(articles)):
response = requests.post(
"https://api.aihumanizerapi.com/v1/humanize/batch",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={"texts": chunk, "tone": "professional"},
timeout=60
)
if response.status_code == 200:
batch_results = response.json()["results"]
results.extend(batch_results)
print(f"Batch {batch_num + 1}/100: {len(batch_results)} articles processed")
else:
print(f"Batch {batch_num + 1} failed: {response.status_code}")
time.sleep(1) # Rate limit buffer
With a 1-second pause between batches, this processes all 10,000 articles in roughly 2-3 minutes. Without the pause, you risk hitting rate limits.
Parallel Processing for Speed
Sequential processing is safe but slow. For maximum throughput, run multiple batch requests concurrently using async I/O:
import asyncio
import aiohttp
async def process_batch(session, chunk, api_key):
async with session.post(
"https://api.aihumanizerapi.com/v1/humanize/batch",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={"texts": chunk},
timeout=aiohttp.ClientTimeout(total=60)
) as response:
return await response.json()
async def process_all(articles, api_key, concurrency=5):
chunks = list(chunk_list(articles, 100))
results = []
async with aiohttp.ClientSession() as session:
for i in range(0, len(chunks), concurrency):
group = chunks[i:i + concurrency]
tasks = [process_batch(session, c, api_key) for c in group]
responses = await asyncio.gather(*tasks, return_exceptions=True)
for resp in responses:
if isinstance(resp, dict) and "results" in resp:
results.extend(resp["results"])
await asyncio.sleep(1)
return results
With 5 concurrent requests, you’re processing 500 articles per round. The entire 10,000-article dataset completes in under a minute. Adjust the concurrency based on your plan’s rate limits.
Error Handling and Retries
At scale, failures happen. Network timeouts, transient 500 errors, rate limit 429 responses. Your code needs to handle all of these gracefully without losing progress.
Implement exponential backoff with jitter for retries:
import random
async def process_with_retry(session, chunk, api_key, max_retries=3):
for attempt in range(max_retries):
try:
result = await process_batch(session, chunk, api_key)
if "results" in result:
return result
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
if attempt == max_retries - 1:
return {"error": str(e), "texts": chunk}
wait = (2 ** attempt) + random.uniform(0, 1)
await asyncio.sleep(wait)
return {"error": "max retries exceeded", "texts": chunk}
The jitter (random addition to wait time) prevents thundering herd problems when multiple failed requests retry simultaneously.
Progress Tracking
When you’re processing 10,000 articles, you need visibility into what’s happening. Log batch completions, track word counts, and estimate time remaining:
import time
total_batches = len(chunks)
completed = 0
total_words = 0
start = time.time()
for batch_num, chunk in enumerate(chunks):
result = process_batch_sync(chunk)
completed += 1
total_words += result.get("total_words_processed", 0)
elapsed = time.time() - start
rate = completed / elapsed
remaining = (total_batches - completed) / rate
print(f"[{completed}/{total_batches}] "
f"Words: {total_words:,} | "
f"Rate: {rate:.1f} batches/sec | "
f"ETA: {remaining:.0f}s")
Handling Partial Failures
In a 100-batch job, maybe 2-3 batches fail. That’s 9,700 successful articles and 300 that need reprocessing. Don’t restart the entire job. Track failures separately:
successful = []
failed_chunks = []
for batch_num, chunk in enumerate(chunks):
result = process_with_retry(chunk)
if "error" in result:
failed_chunks.append(chunk)
else:
successful.extend(result["results"])
# Retry failed chunks
if failed_chunks:
print(f"Retrying {len(failed_chunks)} failed batches...")
for chunk in failed_chunks:
result = process_with_retry(chunk, max_retries=5)
if "results" in result:
successful.extend(result["results"])
Save successful results to your database immediately after each batch. If your script crashes mid-run, you won’t lose completed work.
Cost Estimation
Processing 10,000 articles at an average of 1,500 words each means roughly 15 million words. Check the pricing page for current per-word rates by plan tier. Higher-volume plans offer significantly lower per-word costs.
The batch endpoint itself doesn’t cost more than individual requests. You’re paying the same per-word rate either way. The savings come from reduced overhead and faster processing time, which means less compute time on your end.
Production Deployment Checklist
Before running the full 10,000-article job, validate on a small sample. Process 100 articles first. Spot-check 10-15 results for quality. Verify confidence scores are consistently above 0.85. Confirm your database saves are working correctly.
Once the sample looks good, scale up. Run the full batch during off-peak hours if possible. Monitor progress via your logging output. Have a rollback plan: keep the original content until you’ve verified the humanized versions are satisfactory.
After processing, run a quality audit on a random sample of 50-100 articles. Check that meaning is preserved, tone is consistent, and confidence scores meet your threshold. If any articles score below your cutoff, flag them for re-processing or manual review.
Start Processing at Scale
The batch endpoint turns a multi-day manual process into a sub-5-minute automated job. Whether you’re humanizing a content backlog, processing a new batch of AI-generated articles, or migrating an entire content library, the pattern is the same: chunk, send, collect, verify.
Get your API key and start with the free tier: 10,000 words per month, no credit card required. That’s enough to test your batch pipeline on real content before scaling up.
When to use the batch endpoint
Batch processing earns its place when you have 50+ items in a queue, can tolerate seconds-to-minutes of latency, and want to hit better effective per-word rates on enterprise plans. For real-time editor workflows, stick with the single endpoint – the overhead of batch coordination isn’t worth it under 10 items.
Common patterns we see:
- Overnight content runs – the day’s drafts queued at midnight, results ready by morning
- Migration backfills – re-humanize older AI-drafted posts in chunks of 1,000
- Multi-tenant SaaS – batch each tenant’s requests with their ID for routing
- Translation pipelines – humanize translated output in the target language as a batch step
Frequently asked questions
How many items can I send in one batch?
Up to 100 items per synchronous batch request. For larger jobs, use the async endpoint with a webhook callback – accepts up to 10,000 items per job and processes them in the background.
Are batch requests counted differently against my rate limit?
No. A batch request counts as one against your per-minute API rate limit, regardless of the number of items inside. So a Pro plan at 60 RPM can process 60 batches of 100 = 6,000 humanizations per minute via batch.
What happens if one item in the batch fails?
Individual failures don’t fail the whole batch. Each result includes a success boolean and an error_code if applicable. Iterate and retry only the failed items. See the full schema in our API documentation.
Does batch cost the same per word?
Yes per-word, but Enterprise plans get better effective rates because batch processing is more efficient on our infrastructure. See pricing for tier breakdowns.
Can I mix tones and languages in one batch?
Yes. Each item carries its own tone and language parameters. The engine routes per-item, so you can humanize 100 items spanning 4 tones and 10 languages in a single call.
Get started
Sign up for a free API key (10K words/month, no credit card) and try the batch endpoint with a sample of your typical content. For high-volume use cases, see our use cases page.