Generating content at scale
Batch enrichment across a catalog, reuse rules for consistency, and keep throughput within your limits.
This guide covers generating content for many products: how to batch, how to reuse contextual rules so tone stays consistent, and how to stay inside your rate limit and budget.
Pipeline or content?
Both live in the Contextual Enrichment Engine.
POST /api/v1/enrichment/pipelinederives rules and then generates content in one call. Best for a first run, or a scheduled refresh where the catalog has changed.POST /api/v1/enrichment/contentgenerates content against rules you already hold. Best when you are working through a catalog in batches, because you generate the rules once instead of once per batch.
Both are metered on the content they write, so the cost of a batch follows the number of products and how many content types you ask for. Rules generation itself is free. On a test key, both use one quota unit per product per content type.
Reuse rules across batches
This is the single biggest lever for consistency. /enrichment/content does not derive rules itself: without rules it writes from the product data alone, so reusing one set is also what keeps batches grounded at all.
# 1. Derive rules once, from a representative sample of the category.
curl -s -X POST https://ace.authoritas.com/api/v1/enrichment/rules \
-H "Authorization: Bearer $ACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"mode":"sync","source":{"type":"inline","products":'"$(cat sample.json)"'}}' \
> rules.json
# 2. Reuse them for every batch in that category.
for batch in batches/*.json; do
jq --slurpfile r rules.json \
'{source:{type:"inline",products:.},contentTypes:["product-description","meta-tags"],rules:$r[0].data.rules}' \
"$batch" \
| curl -s -X POST https://ace.authoritas.com/api/v1/enrichment/content \
-H "Authorization: Bearer $ACE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(basename "$batch")" \
-d @-
done"mode": "sync" matters in step 1: a sample of more than 5 products otherwise comes back as a job, not as rules. The rules are in data.rules of the response, which is what step 2 passes on.
Sample per category, not per catalog. Rules describe a category's buying behaviour, so mixing unrelated categories into one sample produces vaguer rules.
Batch sizing and jobs
A pipeline request always returns 202 with a job envelope. A content request does the same beyond 5 products or 10 units (products multiplied by content types), so a long run never sits on an open connection. You do not need to tune this: send natural batches and let the engine decide. On a content request, force the behaviour with "mode": "async" or "mode": "sync" if you need to.
Track the work with the jobs endpoints:
rezolve jobs list --status running
rezolve jobs wait <id>
rezolve jobs results <id> --page-size 200Language and locale
For a multi-locale catalog, detect first and pass the result through:
curl -s -X POST https://ace.authoritas.com/api/v1/utils/language \
-H "Authorization: Bearer $ACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"products":[{"id":"1","title":"Wanderschuhe für Herren"}]}'
# => { "data": { "language": "de-DE", "confidence": "high", "reasoning": "..." } }Detection is free. confidence is high, medium, or low. Feed the returned BCP 47 code into targetLanguage on your content or pipeline request.
Content types
Request as many as you need per product. Each one adds work, and so cost, for every product in the batch.
| Content type | API value |
|---|---|
| Product description | product-description |
| Meta tags and SEO | meta-tags |
| Enhanced JSON-LD schema | jsonld-schema |
| IRL scenario cards | irl-scenarios |
| Internal linking recommendations | internal-links |
| Product title | product-title |
| Highlights and bullet points | highlights |
| Product Q&A | product-qa |
| Product attributes | product-attributes |
| Image alt text | image-alt |
| Google Shopping feed fields | google-shopping |
| Agentic Commerce feed fields | agentic-commerce |
| Microsoft Shopping feed fields | microsoft-shopping |
| Shopify feed fields | shopify |
| WooCommerce feed fields | woocommerce |
A value that is not in this table is skipped rather than rejected, and is listed in skippedContentTypes (on a synchronous response, or on the job's result) so you can see it was not generated or charged. image-alt needs at least one product image with a public URL.
A product description states only what the product data says, plus what a lookup found when lookup is on. Attributes and specifications it cannot trace to the data are left out, and a short product record gets a short description. A description does not mention your other products unless you set crossSell: true, which lets it name one or two products from the project's catalogue so it can carry internal links.
Best practices
- Budget before you start. Measure a small batch, then scale. Check
GET /api/v1/usage. See Credits and usage for per-product planning figures. - Send an idempotency key per batch. A retried batch returns its original job rather than paying twice. Use a stable key such as the batch filename.
- Handle partial success. A job can finish
partial, with bothsucceededCountandfailedCountset. Read/jobs/{id}/resultsand retry only the failures. - Back off on 429. Your key has a requests per minute limit. Honour
Retry-After. See Rate limits for how to set a different limit. - Score before and after.
POST /api/v1/utils/agentic-readinessis free and shows which products are thin on data. Run it first to prioritise, and again afterwards to show the lift. - Prefer webhooks over polling for large runs. See Webhooks.
Summary
- Derive rules once per category, then reuse them across every batch.
- Let large requests become jobs, and track them through the jobs endpoints.
- Detect language for free and pass it through as
targetLanguage. - Use idempotency keys, handle
partialresults, and back off on 429.
For full schemas, see the API Reference.