Skip to main content
PATCH
Use this endpoint when you know a source ID and need to update its metadata in place. It updates both the source row and indexed chunk metadata used by query/list filters.
The legacy route PATCH /context/sources/{source_id}/metadata still works but is deprecated. Migrate to the route above. Both dispatch to the same handler; source_id and id name the same value.

Request

Path parameters

Body

At least one of database_metadata, additional_metadata, or acl is required.
This edit endpoint uses database_metadata for schema-backed source metadata (deprecated alias: tenant_metadata, still accepted, but the canonical field wins if both are sent). The shorter metadata field used by ingestion/list examples is not accepted in this PATCH body. document_metadata is also not accepted; use additional_metadata.

Behavior

  • The update is a merge/upsert:
    • keys present in the request are inserted or overwritten
    • keys omitted from the request are preserved
    • acl is the exception: when sent, it replaces the stored list
  • The source must already exist. This endpoint does not create sources.
  • The endpoint edits one source at a time. Bulk metadata edits are not supported.
  • Updated metadata is visible to /query metadata filters and /context/list filters.
  • If an edited database metadata field has enable_dense_embedding or enable_sparse_embedding, HydraDB synchronously refreshes the relevant vector store metadata search lane.
  • If no edited field has an embedding flag, the edit remains MongoDB-only and vector_sync_required is false.

Response

Validation and errors

If the metadata is written to MongoDB but the dense/sparse vector store sync fails, the call still returns 200, without vector_synced and with vector_sync_error explaining why. Retry the same idempotent edit to converge.

Size limits

database_metadata (and its still-accepted tenant_metadata alias) is capped at 16 KiB; additional_metadata at 1 KiB. Each cap applies to the whole map, measured on its compact JSON encoding in UTF-8 bytes: keys, quotes and punctuation count toward the budget, so budget in bytes rather than in characters of content. The cap is checked against the payload in this request, before the merge, not against the stored map the merge produces. A small edit to an already-large map is therefore accepted, so treat the cap as a per-request budget rather than a guarantee about the final stored size. Over-cap fails the whole edit with 400 and reports both numbers:
See Scoping using metadata: Size limits.

Authorizations

Authorization
string
header
required

API key sent as a Bearer token: "Bearer prefix.secret"

Path Parameters

id
string
required

Source ID

Example:

"HydraDoc1234"

Body

application/json

Metadata update request

acl
string[]

ACL, when present, REPLACES the source's access-control list without re-ingestion (PRO-1684): pass the COMPLETE new allow-list (adding a third user means sending all three), an empty list to make the source private, or ["public"] to open it to every identified caller. A pointer so omitted (nil, ACL untouched) is distinguishable from an explicit empty list (private). ACL uses RawMessage so the handler can tell three wire states apart: absent (leave the stored ACL untouched), explicit null (revoke to nobody, JSON-merge-patch semantics), and a list (replace). A plain *[]string cannot: encoding/json leaves the pointer nil for BOTH absent and null, which silently ignored an explicit null revocation.

additional_metadata
object

Free-form key-value pairs to merge into the source's additional_metadata. The only accepted spelling for document metadata on this endpoint. Capped at 1 KiB, measured on the compact JSON encoding of the whole map in UTF-8 bytes — keys, quotes, commas and braces count toward the budget. Over-cap returns 400 with the actual byte count.

Example:
collection
string

Collection scope. Defaults to the default collection when omitted. Formerly sub_tenant_id; the sub_tenant_id alias is still accepted (deprecated).

Example:

"team_docs"

database
string

Database/Collection are the canonical v2 names; TenantID/SubTenantID are their deprecated aliases. The TenantAliases middleware reconciles them in the request body before binding, so the handler reads TenantID/SubTenantID.

Example:

"acme_corp"

database_metadata
object

Schema-backed metadata fields to merge into the source's metadata (database metadata). Canonical name; tenant_metadata is a deprecated alias. Capped at 16 KiB, measured on the compact JSON encoding of the whole map in UTF-8 bytes — keys, quotes, commas and braces count toward the budget. Over-cap returns 400 with the actual byte count.

Example:
document_metadata
object
deprecated

Not accepted on this endpoint. Sending any non-null value returns 400 (document_metadata is not accepted; use additional_metadata), regardless of size. Use additional_metadata instead. Accepted as an alias on /context/ingest only.

sub_tenant_id
string
deprecated

deprecated: use collection

Example:

"sub_tenant_4567"

tenant_id
string
deprecated

deprecated: use database

Example:

"tenant_1234"

tenant_metadata
object
deprecated

Deprecated alias for database_metadata, still accepted here; database_metadata wins when both are sent. Capped at 16 KiB, measured on the compact JSON encoding of the whole map in UTF-8 bytes — keys, quotes, commas and braces count toward the budget. Over-cap returns 400 with the actual byte count.

Example:

Response

OK

data
object
Example:
error
object | null

Null on success; an object with code and message on failure.

Example:

null

meta
object
Example:
success
boolean

Whether the request succeeded.

Example:

true