Skip to content

Terms Extraction

Terms extraction finds the terms worth keeping consistent in a text (names, product features, defined terms, domain vocabulary) and adds them to a glossary, translated into every language of that glossary.

It works in two steps, so you can review the candidates before anything is added:

  1. Extract. POST /translation/glossaries/{id}/extract starts a background task that returns term candidates. The glossary does not change.
  2. Save. After your review, POST /translation/glossaries/{id}/terms/save translates the terms you kept into all glossary languages and adds them.

Both steps return a taskId. Follow a task with GET /translation/glossaries/tasks/{taskId}, or pass a callbackUrl to be notified when it finishes (see Callbacks). To skip the review, send autoSave: true with the extraction and it saves the new candidates itself.

Returns the limits for extraction and saving, the depth levels, and ready-made instruction presets.

Endpoint: GET /translation/glossaries/extract/config

Success Response (200)

{
"status": "ok",
"timestamp": "2026-10-29T10:00:00.000Z",
"data": {
"limits": {
"maxTextLength": 200000,
"maxCustomPromptLength": 5000,
"maxTerms": 500,
"maxSaveTerms": 500,
"maxTermLength": 200,
"maxDefinitionLength": 1000
},
"depths": ["key", "balanced", "exhaustive"],
"defaultDepth": "balanced",
"presets": [
{
"id": "game-lore",
"label": "Game & lore",
"description": "Characters, places, factions, items and abilities",
"instructions": "This is game or fiction content. Extract every proper name: characters, places, factions, organizations, titles and ranks. ..."
}
]
}
}
Field Description
limits.maxTextLength Longest text accepted by extraction, in characters
limits.maxCustomPromptLength Longest customPrompt, in characters
limits.maxTerms Highest allowed maxTerms
limits.maxSaveTerms Most terms per save request
limits.maxTermLength, limits.maxDefinitionLength Longest term and definition accepted by save, in characters
depths, defaultDepth Accepted depth values and the one used when you send none
presets Instruction texts for common kinds of content: game-lore, software-ui, legal, medical and marketing. Send a preset’s instructions as customPrompt as it is, or adapt it to your content
Terminal window
curl -X GET "https://platform.algebras.ai/api/v1/translation/glossaries/extract/config" \
-H "X-Api-Key: your_api_key_here"

Starts extracting term candidates from a text. Long texts are split into parts that are processed in parallel. The glossary does not change unless you send autoSave: true.

Endpoint: POST /translation/glossaries/{id}/extract

  • id: The glossary ID

Sent as JSON.

Field Type Required Description
text string yes Text to extract terms from, up to limits.maxTextLength characters
customPrompt string no Your instructions for what to extract, for example “Include every character, place and spell name.” They take precedence over the default selection criteria. A preset is a good starting point
depth string no How many terms to aim for. key: only the core terms a translator must keep consistent. balanced (default): every term worth keeping consistent, skipping obvious words. exhaustive: every candidate, including minor names and one-off mentions
maxTerms integer no Upper bound on the number of new candidates, 1 to limits.maxTerms. The ones that occur most often in the text are kept
includeDefinitions boolean no Generate a short definition for each term (default true). Turn it off for a term list only: it is faster and leaves room for more terms
autoSave boolean no Translate and save the new candidates without review (default false). The task then has the type extract_and_save and is billed like a save
callbackUrl string no An https URL that receives an event when the task finishes. See Callbacks

Accepted (202)

{
"status": "ok",
"timestamp": "2026-10-29T10:00:00.000Z",
"data": {
"taskId": "f3b9c2e1-7a4d-4c1e-9b0a-2d6e8f1a5c37"
}
}

Error Responses

Status When
400 Invalid body, for example a text longer than limits.maxTextLength or a callbackUrl that is not https
402 The organization has no quota left or has unpaid invoices
404 The glossary does not exist in your organization
Terminal window
curl -X POST "https://platform.algebras.ai/api/v1/translation/glossaries/cmglossary123/extract" \
-H "X-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"text": "Aldric raised the Dragon Stone above the gates of Vel'\''Shara. The Ember Guard knelt.",
"customPrompt": "Include every character, place and artifact name.",
"depth": "balanced",
"maxTerms": 50
}'

Returns the state, progress and result of an extraction or save task. Poll every few seconds until state is succeeded or failed. Tasks are kept for 7 days.

Endpoint: GET /translation/glossaries/tasks/{taskId}

  • taskId: The task ID returned when the task was started

Success Response (200), a finished extraction:

{
"status": "ok",
"timestamp": "2026-10-29T10:01:12.000Z",
"data": {
"taskId": "f3b9c2e1-7a4d-4c1e-9b0a-2d6e8f1a5c37",
"type": "extract",
"state": "succeeded",
"glossaryId": "cmglossary123",
"progress": { "phase": "extracting", "done": 2, "total": 2 },
"result": {
"terms": [
{ "term": "Dragon Stone", "definition": "A rare magical artifact that powers the city gates.", "occurrences": 7, "exists": false },
{ "term": "Ember Guard", "definition": "The order of knights that protects Vel'Shara.", "occurrences": 3, "exists": false },
{ "term": "Aldric", "definition": "The king of Vel'Shara.", "occurrences": 12, "exists": true }
],
"chunks": 2,
"failedChunks": [],
"truncated": false
},
"error": null,
"createdAt": "2026-10-29T10:00:00.000Z",
"updatedAt": "2026-10-29T10:01:10.000Z"
}
}
Field Description
type extract, save, or extract_and_save for an extraction with autoSave
state pending, running, succeeded or failed
progress phase is extracting (done/total count text parts) or saving (they count terms). null before the task starts
error Why the task failed, when state is failed
result Set once the task has finished. The fields below depend on the task type

Extraction result (extract and extract_and_save)

Field Description
terms Candidates, each with term, definition, occurrences (how often it occurs in the text) and exists. New candidates come first, ranked by occurrences, then the terms the glossary already has (exists: true)
chunks Number of parts the text was split into
failedChunks Zero-based indexes of parts that could not be processed. The candidates from the other parts are still returned; run the extraction again to cover these parts
truncated true when maxTerms cut off some candidates

Save result (save and extract_and_save)

Field Description
added Number of terms translated and saved
skipped Terms not saved, each with term and reason (exists when the glossary already has it)
failed Terms that could not be translated, each with term and error. They were not saved or billed
Terminal window
curl -X GET "https://platform.algebras.ai/api/v1/translation/glossaries/tasks/f3b9c2e1-7a4d-4c1e-9b0a-2d6e8f1a5c37" \
-H "X-Api-Key: your_api_key_here"

Translates terms into every language of the glossary and adds them. Send the final list after your review: leave out the candidates you rejected, include terms you added yourself, and send edited terms and definitions as they are. The review happens on your side, so you can also save terms that did not come from an extraction.

Terms the glossary already has are skipped, so resending the same request is safe. If you already have translations for your terms, use Create Multiple Terms (Bulk) instead.

Endpoint: POST /translation/glossaries/{id}/terms/save

  • id: The glossary ID

Sent as JSON.

Field Type Required Description
terms array of objects yes Terms to save, up to limits.maxSaveTerms
terms[].term string yes The term, up to limits.maxTermLength characters
terms[].definition string no A short definition, up to limits.maxDefinitionLength characters. It is translated along with the term
extractionTaskId string no The extraction task the terms came from, if any
callbackUrl string no An https URL that receives an event when the task finishes. See Callbacks

Accepted (202)

{
"status": "ok",
"timestamp": "2026-10-29T10:03:00.000Z",
"data": {
"taskId": "9d1e4b7a-2c3f-4e8d-a6b5-0f7c1d2e3a4b"
}
}

Follow the task with Get Task Status. Its result has added, skipped and failed.

Error Responses

Status When
400 Invalid body, for example too many terms
402 The organization has no quota left or has unpaid invoices
404 The glossary does not exist in your organization
409 The glossary is being updated, for example by another save task. Wait for it to finish and retry
Terminal window
curl -X POST "https://platform.algebras.ai/api/v1/translation/glossaries/cmglossary123/terms/save" \
-H "X-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"terms": [
{ "term": "Dragon Stone", "definition": "A rare magical artifact that powers the city gates." },
{ "term": "Ember Guard" }
],
"extractionTaskId": "f3b9c2e1-7a4d-4c1e-9b0a-2d6e8f1a5c37"
}'

Instead of polling, pass a callbackUrl when you start a task. When the task finishes, the platform sends a POST request with a JSON event to that URL:

{
"event": "glossary.task.completed",
"eventId": "6c2f0a9e-1b3d-4f5a-8e7c-9d0b1a2c3e4f",
"taskId": "f3b9c2e1-7a4d-4c1e-9b0a-2d6e8f1a5c37",
"type": "extract",
"state": "succeeded",
"glossaryId": "cmglossary123",
"completedAt": "2026-10-29T10:01:10.000Z"
}

The event carries no result: fetch it with Get Task Status. state is succeeded or failed.

  • The URL must use https, must not contain credentials, and its host must resolve to a public address. Otherwise the request that starts the task fails with 400.
  • Answer with any 2xx status to acknowledge the event. Otherwise delivery is retried up to 4 times: after 1 minute, 5 minutes, 30 minutes and 2 hours.
  • A retry has the same eventId, so use it to drop duplicates.

A minimal receiver in Node.js:

import { createServer } from "node:http";
const seen = new Set();
createServer(async (req, res) => {
let body = "";
for await (const chunk of req) body += chunk;
res.writeHead(200).end(); // acknowledge first
const event = JSON.parse(body);
if (seen.has(event.eventId)) return;
seen.add(event.eventId);
console.log(`Task ${event.taskId} (${event.type}) ${event.state}`);
// Fetch the result with GET /translation/glossaries/tasks/{taskId}
}).listen(3000);

To extract and save in one call, send autoSave: true. Only new candidates are saved, and the task’s result has both the extraction fields and added, skipped and failed:

Terminal window
curl -X POST "https://platform.algebras.ai/api/v1/translation/glossaries/cmglossary123/extract" \
-H "X-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"text": "Aldric raised the Dragon Stone above the gates of Vel'\''Shara.",
"depth": "key",
"autoSave": true,
"callbackUrl": "https://example.com/hooks/algebras"
}'

Use depth: "key" or a maxTerms cap here: without a review, every candidate is translated and billed.