Developer guide

Clausa

A Belumind product · Vietnamese administrative & legal text

Product page

Reads the text of decisions, official letters, decrees and circulars — straight from your OCR, or typed without accents — and pulls out who issued each one, its number, date, who signed it and which laws it relies on. It also shows how documents connect: which one cites, replaces or cancels another. It is small enough to run on your own servers, so your documents never leave your organisation.

Address for your software (API)

https://api2.belumind.com/clausa

Address for AI assistants (MCP)

https://mcp2.belumind.com/clausa
Accuracy (details / links)
90.0 / 81.2
Fast server (A100 GPU)
0.20 s / page
Regular server (Xeon CPU)
5.09 s / page
Size
< 0.5 billion parameters

Access keys

Every request sends two things: an API key for this product, made in the dashboard under API keys, and the access token of the signed-in user who owns it. The token lasts 15 minutes, so refresh it and send the new one. A key made for another product gets a 403 error. That means you can give an AI assistant a key that reaches exactly one tool and nothing else.

AI assistants send the same two headers when they connect to the address above.

clausa:extract
How the keys are sent
X-API-Key: bm_live_7f3c…
Authorization: Bearer eyJhbGciOi…
Content-Type: application/json
POST/v1/extract/schemaclausa:extract

Read a document's key details

Send the text of an official document — Clausa does not open PDFs or images, so run OCR first — and get back its number, issuing body, issue date (as `YYYY-MM-DD`), signer, the signer's position and the documents it is based on. The built-in `administrative_document` schema covers these; `GET /v1/schemas` (MCP: `list_schemas`) lists it with every field. A field Clausa cannot find comes back empty rather than guessed, and `warnings` names any required field that is missing. Texts over 20,000 characters go to `POST /v1/jobs/schema` instead.

AI assistant toolextract_document_fields

What to send

textstringrequired
The document's text, UTF-8 — for example the output of your OCR.
schema_namestringoptional
A built-in schema from `GET /v1/schemas`, such as `administrative_document`. Send this or `schema` — the REST API has no default, so a request with neither gets error 422. (The MCP tool defaults to `administrative_document`.)
schemaobjectoptional
Your own fields instead of a built-in schema: each names a label and, optionally, a relation it must have. `GET /v1/examples` shows four. Send this or `schema_name`.
postprocessbooleanoptional
Clean up OCR text before reading it — drop digital-signature stamps, logos and repeated lines, fix QD to QĐ, pair the signer with their position. On by default; every change is listed in `postprocess.edits`.
detailbooleanoptional
Also return the candidates, raw entities and relations behind each field, and the cleaned text. For debugging.

What you get back

  • 200 OKIt worked. You get back what the example shows.
  • 400 Bad RequestSomething in what you sent was wrong or missing. The answer says which part.
  • 401 UnauthorizedThe API key or access token is missing, mistyped or no longer valid. Access tokens expire after 15 minutes — refresh it and send the new one.
  • 403 ForbiddenThe key works, but it was made for another product.
  • 402 Payment RequiredThe account is out of credits. Buy more in the dashboard, or turn on automatic top-up.
  • 429 Too Many RequestsToo many requests in a short time, or the key has reached the monthly limit set on it. Wait the number of seconds given in `Retry-After`, then try again.
  • 500 Internal Server ErrorSomething went wrong on our side. It is safe to send the same request again.
  • 503 Service UnavailableThe queue is full, or the dashboard that checks keys could not be reached. Try again a little later.

What you send

curl -X POST https://api2.belumind.com/clausa/v1/extract/schema \
  -H "X-API-Key: $BELUMIND_API_KEY" \
  -H "Authorization: Bearer $BELUMIND_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "ỦY BAN NHÂN DÂN TỈNH THANH VÂN\nSố: 1482/QD-UBND\nThanh Vân, ngày 18 tháng 3 năm 2026\nQUYẾT ĐỊNH\nVề việc ban hành Quy chế lưu trữ hồ sơ điện tử\nCăn cứ Luật Lưu trữ ngày 21 tháng 6 năm 2024;\nCăn cứ Nghị định số 118/2024/NĐ-CP;\n…\nKT. CHỦ TỊCH\nPHÓ CHỦ TỊCH\nTrần Minh Khải",
  "schema_name": "administrative_document"
}'

What you get back

application/json200 OK
{
  "result": {
    "document_number": "1482/QĐ-UBND",
    "issuing_authority": "ỦY BAN NHÂN DÂN TỈNH THANH VÂN",
    "issue_date": "2026-03-18",
    "signer": "Trần Minh Khải",
    "signer_title": "Phó Chủ tịch",
    "legal_bases": [
      "Luật Lưu trữ",
      "Nghị định số 118/2024/NĐ-CP"
    ]
  },
  "warnings": [],
  "device": "mps",
  "seconds": 0.59,
  "postprocess": {
    "lines_removed": 0,
    "edits": [
      {
        "field": "document_number",
        "before": "1482/QD-UBND",
        "after": "1482/QĐ-UBND",
        "reason": "document_type_code"
      },
      {
        "field": "signer_title",
        "before": "Phó chủ tịch",
        "after": "Phó Chủ tịch",
        "reason": "dictionary"
      }
    ]
  }
}

Try it

Try it

Example mode
POST https://api2.belumind.com/clausa/v1/extract/schema

The platform is in early access, so this box shows the example answer instead of contacting the live service. Ask us for a key and the same box will send real requests.

POST/v1/extractclausa:extract

Find names, dates and the links between them

Ask for the kinds of thing you want — people, positions, organisations, dates, documents — and the links between them, such as who holds which position or which decision replaces which. Each entity comes back with its place in the text and a confidence score; each link points to two entities by id. Clausa was trained on the labels from `GET /v1/labels`; other labels work too, less accurately. Add `?download=true` to get the result as a JSON file. `POST /v1/extract/batch` takes several of these requests at once, as `items`, and reads them one after another.

AI assistant toolextract_entities

What to send

textstringrequired
The text to read, UTF-8. Long texts are split into chunks automatically.
entitiesstring[]required
Labels to find, in Vietnamese with diacritics — for example `người`, `chức vụ`, `tổ chức`, `ngày`.
relationsstring[]optional
Links to find between entities, such as `giữ chức` (holds position) or `thay thế` (replaces). May be empty.
thresholdnumberoptional
Lowest confidence, 0–1, for an entity to be kept. Defaults to each label's own threshold (0.5).
relation_thresholdnumberoptional
Lowest confidence, 0–1, for a link to be kept. Defaults to 0.5.
max_words_per_chunkintegeroptional
Largest piece, in words, that a long text is split into before reading, 10–200. Defaults to 40, which measured best.

What you get back

  • 200 OKIt worked. You get back what the example shows.
  • 400 Bad RequestSomething in what you sent was wrong or missing. The answer says which part.
  • 401 UnauthorizedThe API key or access token is missing, mistyped or no longer valid. Access tokens expire after 15 minutes — refresh it and send the new one.
  • 403 ForbiddenThe key works, but it was made for another product.
  • 402 Payment RequiredThe account is out of credits. Buy more in the dashboard, or turn on automatic top-up.
  • 429 Too Many RequestsToo many requests in a short time, or the key has reached the monthly limit set on it. Wait the number of seconds given in `Retry-After`, then try again.
  • 500 Internal Server ErrorSomething went wrong on our side. It is safe to send the same request again.
  • 503 Service UnavailableThe queue is full, or the dashboard that checks keys could not be reached. Try again a little later.

What you send

curl -X POST https://api2.belumind.com/clausa/v1/extract \
  -H "X-API-Key: $BELUMIND_API_KEY" \
  -H "Authorization: Bearer $BELUMIND_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "Bổ nhiệm ông Nguyễn Văn An, Phó Giám đốc Sở Tài chính tỉnh Nghệ An, giữ chức Giám đốc Sở Tài chính tỉnh Nghệ An kể từ ngày 01 tháng 3 năm 2024.",
  "entities": [
    "người",
    "chức vụ",
    "tổ chức",
    "ngày"
  ],
  "relations": [
    "giữ chức",
    "thuộc tổ chức"
  ]
}'

What you get back

application/json200 OK
{
  "entities": [
    {
      "id": "e1",
      "text": "Nguyễn Văn An",
      "label": "người",
      "start": 13,
      "end": 26,
      "score": 0.9629
    },
    {
      "id": "e2",
      "text": "Phó Giám đốc",
      "label": "chức vụ",
      "start": 28,
      "end": 40,
      "score": 0.875
    },
    {
      "id": "e3",
      "text": "Sở Tài chính tỉnh Nghệ An",
      "label": "tổ chức",
      "start": 41,
      "end": 66,
      "score": 0.7334
    },
    {
      "id": "e4",
      "text": "Giám đốc",
      "label": "chức vụ",
      "start": 77,
      "end": 85,
      "score": 0.7603
    },
    {
      "id": "e5",
      "text": "Sở Tài chính tỉnh Nghệ An",
      "label": "tổ chức",
      "start": 86,
      "end": 111,
      "score": 0.7329
    },
    {
      "id": "e6",
      "text": "ngày 01 tháng 3 năm 2024",
      "label": "ngày",
      "start": 118,
      "end": 142,
      "score": 0.9536
    }
  ],
  "relations": [
    {
      "head": "e1",
      "relation": "giữ chức",
      "tail": "e2",
      "score": 0.6558,
      "head_text": "Nguyễn Văn An",
      "tail_text": "Phó Giám đốc"
    },
    {
      "head": "e1",
      "relation": "thuộc tổ chức",
      "tail": "e3",
      "score": 0.8726,
      "head_text": "Nguyễn Văn An",
      "tail_text": "Sở Tài chính tỉnh Nghệ An"
    },
    {
      "head": "e1",
      "relation": "giữ chức",
      "tail": "e4",
      "score": 0.8149,
      "head_text": "Nguyễn Văn An",
      "tail_text": "Giám đốc"
    }
  ],
  "meta": {
    "device": "mps",
    "chunks": 1,
    "max_words_per_chunk": 40,
    "entity_labels_queried": [
      "người",
      "chức vụ",
      "tổ chức",
      "ngày"
    ],
    "relation_labels_queried": [
      "giữ chức",
      "thuộc tổ chức"
    ],
    "seconds": 0.687,
    "warnings": []
  }
}

Try it

Try it

Example mode
POST https://api2.belumind.com/clausa/v1/extract

The platform is in early access, so this box shows the example answer instead of contacting the live service. Ask us for a key and the same box will send real requests.

POST/v1/jobs/schemaclausa:extract

Send a long document to read in the background

For texts over 20,000 characters, up to 1,000,000. Takes the same body as `POST /v1/extract/schema` and answers at once with a job id; check `GET /v1/jobs/{job_id}` until `status` is `done`. `POST /v1/jobs/extract` does the same for `POST /v1/extract`.

AI assistant toolsubmit_job

What to send

textstringrequired
The document's text, UTF-8, up to 1,000,000 characters.
schema_namestringoptional
A built-in schema, such as `administrative_document`. The other fields of `POST /v1/extract/schema` work here too.

What you get back

  • 202 AcceptedReceived — it is in line to be processed.
  • 400 Bad RequestSomething in what you sent was wrong or missing. The answer says which part.
  • 401 UnauthorizedThe API key or access token is missing, mistyped or no longer valid. Access tokens expire after 15 minutes — refresh it and send the new one.
  • 403 ForbiddenThe key works, but it was made for another product.
  • 402 Payment RequiredThe account is out of credits. Buy more in the dashboard, or turn on automatic top-up.
  • 429 Too Many RequestsToo many requests in a short time, or the key has reached the monthly limit set on it. Wait the number of seconds given in `Retry-After`, then try again.
  • 500 Internal Server ErrorSomething went wrong on our side. It is safe to send the same request again.
  • 503 Service UnavailableThe queue is full, or the dashboard that checks keys could not be reached. Try again a little later.

What you send

curl -X POST https://api2.belumind.com/clausa/v1/jobs/schema \
  -H "X-API-Key: $BELUMIND_API_KEY" \
  -H "Authorization: Bearer $BELUMIND_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "ỦY BAN NHÂN DÂN TỈNH THANH VÂN\nSố: 1482/QD-UBND\n…",
  "schema_name": "administrative_document"
}'

What you get back

application/json202 Accepted
{
  "id": "8c41f2a0d3b94e6f9a1c5b7e2d40f318",
  "kind": "schema",
  "status": "queued",
  "queue_position": 1,
  "created_at": 1774512000.5,
  "started_at": null,
  "finished_at": null,
  "progress": {
    "chunks_done": 0,
    "chunks_total": null
  },
  "error": null,
  "result": null
}

Try it

Try it

Example mode
POST https://api2.belumind.com/clausa/v1/jobs/schema

The platform is in early access, so this box shows the example answer instead of contacting the live service. Ask us for a key and the same box will send real requests.

GET/v1/jobs/{job_id}clausa:extract

Check a background job

Shows where a job is — `queued`, `running`, `done`, `failed` or `cancelled` — and how many chunks are read so far. Once it is `done`, `result` holds the same JSON the synchronous endpoint would have returned. `DELETE /v1/jobs/{job_id}` cancels a job that is still queued.

AI assistant toolget_job

Settings in the address

job_idstringrequired
The `id` returned by `POST /v1/jobs/schema` or `POST /v1/jobs/extract`.

What you get back

  • 200 OKIt worked. You get back what the example shows.
  • 400 Bad RequestSomething in what you sent was wrong or missing. The answer says which part.
  • 401 UnauthorizedThe API key or access token is missing, mistyped or no longer valid. Access tokens expire after 15 minutes — refresh it and send the new one.
  • 403 ForbiddenThe key works, but it was made for another product.
  • 402 Payment RequiredThe account is out of credits. Buy more in the dashboard, or turn on automatic top-up.
  • 429 Too Many RequestsToo many requests in a short time, or the key has reached the monthly limit set on it. Wait the number of seconds given in `Retry-After`, then try again.
  • 500 Internal Server ErrorSomething went wrong on our side. It is safe to send the same request again.
  • 503 Service UnavailableThe queue is full, or the dashboard that checks keys could not be reached. Try again a little later.

What you send

curl -X GET https://api2.belumind.com/clausa/v1/jobs/{job_id} \
  -H "X-API-Key: $BELUMIND_API_KEY" \
  -H "Authorization: Bearer $BELUMIND_ACCESS_TOKEN"

What you get back

application/json200 OK
{
  "id": "8c41f2a0d3b94e6f9a1c5b7e2d40f318",
  "kind": "schema",
  "status": "done",
  "queue_position": null,
  "created_at": 1774512000.5,
  "started_at": 1774512001.1,
  "finished_at": 1774512019.8,
  "progress": {
    "chunks_done": 212,
    "chunks_total": 212
  },
  "error": null,
  "result": {
    "result": {
      "document_number": "1482/QĐ-UBND",
      "issuing_authority": "ỦY BAN NHÂN DÂN TỈNH THANH VÂN",
      "issue_date": "2026-03-18",
      "signer": "Trần Minh Khải",
      "signer_title": "Phó Chủ tịch",
      "legal_bases": [
        "Luật Lưu trữ",
        "Nghị định số 118/2024/NĐ-CP"
      ]
    },
    "warnings": [],
    "device": "mps",
    "seconds": 18.7
  }
}

Try it

Try it

Example mode
GET https://api2.belumind.com/clausa/v1/jobs/

The platform is in early access, so this box shows the example answer instead of contacting the live service. Ask us for a key and the same box will send real requests.

GET/v1/labelsclausa:extract

List the labels Clausa knows best

The entity and link labels Clausa was trained on — use them in `POST /v1/extract` for the best accuracy. When you ask for a link, Clausa also looks for the labels in its `tail_default`. Needs no key, like `GET /v1/schemas` and `GET /v1/examples`.

AI assistant toollist_labels

What you get back

  • 200 OKIt worked. You get back what the example shows.
  • 400 Bad RequestSomething in what you sent was wrong or missing. The answer says which part.
  • 401 UnauthorizedThe API key or access token is missing, mistyped or no longer valid. Access tokens expire after 15 minutes — refresh it and send the new one.
  • 403 ForbiddenThe key works, but it was made for another product.
  • 402 Payment RequiredThe account is out of credits. Buy more in the dashboard, or turn on automatic top-up.
  • 429 Too Many RequestsToo many requests in a short time, or the key has reached the monthly limit set on it. Wait the number of seconds given in `Retry-After`, then try again.
  • 500 Internal Server ErrorSomething went wrong on our side. It is safe to send the same request again.
  • 503 Service UnavailableThe queue is full, or the dashboard that checks keys could not be reached. Try again a little later.

What you send

curl -X GET https://api2.belumind.com/clausa/v1/labels \
  -H "X-API-Key: $BELUMIND_API_KEY" \
  -H "Authorization: Bearer $BELUMIND_ACCESS_TOKEN"

What you get back

application/json200 OK
{
  "entity_labels": [
    "văn bản",
    "số hiệu văn bản",
    "tổ chức",
    "người",
    "chức vụ",
    "ngày",
    "địa điểm",
    "điều khoản",
    "đối tượng áp dụng",
    "số lượng",
    "thời hạn",
    "giấy tờ"
  ],
  "relation_labels": [
    {
      "name": "ban hành bởi",
      "tail_default": [
        "tổ chức"
      ]
    },
    {
      "name": "ban hành ngày",
      "tail_default": [
        "ngày"
      ]
    },
    {
      "name": "giữ chức",
      "tail_default": [
        "chức vụ"
      ]
    },
    {
      "name": "thuộc tổ chức",
      "tail_default": [
        "tổ chức"
      ]
    },
    {
      "name": "thay thế",
      "tail_default": [
        "văn bản"
      ]
    },
    {
      "name": "bãi bỏ",
      "tail_default": [
        "văn bản"
      ]
    },
    {
      "name": "ký",
      "tail_default": [
        "văn bản",
        "số hiệu văn bản"
      ]
    }
  ]
}

Try it

Try it

Example mode
GET https://api2.belumind.com/clausa/v1/labels

The platform is in early access, so this box shows the example answer instead of contacting the live service. Ask us for a key and the same box will send real requests.

Use with an AI assistant

Connected to an AI assistant, Clausa lets it read a stack of official documents and answer questions about how they relate — which decision replaced which, who signed it, which law it is based on — quoting the exact details instead of retelling the text. Because Clausa runs on your own servers, the documents stay inside your organisation.

You ask

“Which of these decisions are still in force, and what did 1482/QĐ-UBND replace?”

The assistant

  1. 01Sends the text of each document to Clausa
  2. 02Follows which documents replace or cancel others
  3. 03Answers with document numbers and signers, and points out any detail Clausa was not sure about
Settings to paste into your AI assistant
{
  "mcpServers": {
    "clausa": {
      "url": "https://mcp2.belumind.com/clausa",
      "headers": {
        "X-API-Key": "bm_live_7f3c…",
        "Authorization": "Bearer eyJhbGciOi…"
      }
    }
  }
}

When something goes wrong

When a request fails, you get a standard error number and a short code that your software can act on, next to a plain message for people to read. Each request can carry an Idempotency-Key, so sending it again after a problem on our side is safe — it won't be done twice.

What an error looks like4xx / 5xx
{
  "error": {
    "code": "invalid_parameter",
    "message": "`url` must be a reachable http(s) URL.",
    "param": "url",
    "request_id": "req_4d91c0b7"
  }
}

Ready to use it for real?

While the platform is in early access, the "Try it" box shows example answers. Tell us what you are building and we will get you a key.