Entity Curation
Review, validate, and correct the entities bem extracts
bem builds an entity memory automatically as it parses documents — the nodes and edges you read through the Knowledge Graph API, shaped by the types and synonyms you define in the Customer Ontology. Curation is the human-in-the-loop layer over that memory: a reviewer works through the entities Parse extracted, approves the ones that are right, rejects the noise, and fixes types and synonyms along the way.
PATCH /v3/entities/{id}
POST /v3/entities/bulk-validate
x-api-key: <your API key>Concepts
The entity lifecycle
Every entity carries a curation status. It begins pre-terminal and
a reviewer moves it to a terminal state:
status | Meaning |
|---|---|
extracted | bem inferred the entity while parsing a document. Awaiting review. |
proposed | Queued for a reviewer's attention. Awaiting review. |
approved | A reviewer confirmed the entity. Terminal. |
rejected | A reviewer discarded the entity. Terminal. |
Approving or rejecting is only allowed from extracted or
proposed. Any other transition — re-approving a terminal entity, for
example — is rejected with 409. Once an entity is validated,
validatedAt and validatedByUserID record who closed it out and when.
Reviewers are a dashboard concept, not an API-key one
Curation is scoped by entity type, and someone with dashboard access
can assign reviewers per type. That assignment, and the lookup of "every
type a given user reviews," both live on the session-authenticated
dashboard surface — /v3/entity-types/{typeID}/reviewers and
/v3/users/{userID}/reviewer-assignments accept a dashboard session
(JWT) only, never an x-api-key. An API-key integration can't manage or
read reviewer assignments; if you need "who reviews what" in your own
system, track it yourself.
There is currently no API-key-reachable way to list entities awaiting review.
The read surface this page used to document (GET /v3/review-queue) doesn't
exist on any surface — not the API, not the dashboard — so it isn't a scoping
issue you can work around with a different auth mode. If your integration
needs to discover pending entities, you need your own bookkeeping (for
example, tracking entity IDs off webhooks and other events you already
receive) until this gap closes. Flagging it rather than guessing at a
substitute.
Alias resolution
Curation endpoints honor merges. If you hold an entity id that was later
merged away, PATCH /v3/entities/{id} resolves it to the surviving
canonical entity and operates on that — you never act on a dead id by
accident.
Curating entities
Approve, reject, or correct one entity
PATCH /v3/entities/{id} updates a single entity. Every field is
optional, but at least one must be present.
| Field | Notes |
|---|---|
status | approved or rejected — only from extracted / proposed, else 409. |
assignedTypeID | ety_… to override the inferred type. The empty string clears the assignment. |
canonical | Replace the canonical surface form (re-derives its normalized form). |
addSynonyms | string[] — surface forms to attach as customer_defined synonyms. |
removeSynonymIDs | esn_… IDs to soft-delete. Only customer_defined / sme_approved synonyms; removing an extracted one is 409. |
locale | Optional BCP 47 tag stamped on any added synonyms. |
An optional bucket query param (bkt_…) scopes the lookup to one bucket; omit it for the default bucket.
# approve an entity and pin its type in one call
curl -X PATCH "https://api.bem.ai/v3/entities/ent_acme" \
-H "x-api-key: $BEM_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "approved", "assignedTypeID": "ety_manufacturer", "addSynonyms": ["Acme Inc."] }'Approving emits an entity_validated webhook; rejecting emits
entity_rejected. The response is the full updated entity record,
including its new status, validatedAt, and validatedByUserID.
Validate in bulk
POST /v3/entities/bulk-validate applies one terminal status to many
entities at once — the workhorse behind "approve all" in a curation
session. It takes the same optional bucket query param as PATCH, above.
curl -X POST "https://api.bem.ai/v3/entities/bulk-validate" \
-H "x-api-key: $BEM_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "entityIDs": ["ent_acme", "ent_globex"], "status": "approved" }'The response reports a per-row outcome (in request order) plus an
aggregate summary, so a partially-valid batch still tells you exactly
what happened:
{
"results": [
{ "entityID": "ent_acme", "outcome": "validated" },
{
"entityID": "ent_globex",
"outcome": "rejected-row",
"reason": "already terminal"
},
{ "entityID": "ent_missing", "outcome": "skipped", "reason": "not found" }
],
"summary": { "validated": 1, "skipped": 1, "rejectedRow": 1 }
}outcome | Meaning |
|---|---|
validated | The transition was applied. |
skipped | Entity not found, or not authorized for the caller. |
rejected-row | The transition itself was illegal (e.g. already terminal). |