---
title: Update metadata fields
description: List, change, or remove the file metadata fields that filters can read.
doc_version: 0.1.0-preview
last_updated: 2026-09-14
---

# Update metadata fields

`PATCH /namespaces/{namespace}/collections/{collection}/metadata-fields`

List, change, or remove the file metadata fields that filters can read.

**Permission:** Cluster key, or a scoped key with write on this collection.

[API key types and authentication](/engine/reference/authentication.md).

Fields that you omit keep their type. Send null for a field to remove it from the list.

A change returns 202 with a reindex_metadata job. Filters are checked against the new fields at once, so a removed key returns not_listed, but they read the old index until the job succeeds. A request that changes nothing returns 200 with the fields, also while a job runs.

On a collection with no files, the job succeeds at once. On a collection with files, the index is rebuilt in the background, and the job stays running until the rebuild is done. Poll Get job until it succeeds.

A collection lists at most 256 fields. A change while the index of the last change is still being rebuilt returns operation_in_progress.

## Example request

```http
PATCH /namespaces/acme/collections/incident-logs/metadata-fields HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "fields": {
    "environment": {
      "type": "text"
    },
    "severity": {
      "type": "number"
    }
  }
}
```

## Path parameters

### `namespace`

**string · required**

Namespace name or ns_ ID. It must be visible to this key.

### `collection`

**string · required**

Collection name or col_ ID within the namespace. It must be visible to this key.

## Request body

### `fields`

**map<string, object> · required**

Map of metadata key to its setting. A setting lists the field with that type. null removes the field. Keys that you omit keep their setting.

#### `fields[key].type`

**string · required**

How filters read the values of this field.

- `text`: Text. A number or a boolean is read as its JSON text. Compares in byte order.
- `number`: A number, or a string that holds a plain decimal number.
- `time`: An RFC 3339 date or date-time. Compares instants, so time zone offsets count.
- `bool`: true or false, or the string "true" or "false".

## Responses

### 200 · No change

The request gave the same fields. The response is the field list.

#### Request for this response

```http
PATCH /namespaces/acme/collections/incident-logs/metadata-fields HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "fields": {
    "environment": {
      "type": "text"
    }
  }
}
```

Content type: `application/json`.

#### Response headers

##### `x-engine-request-id`

**string · required**

The Engine request ID. Retain it when investigating a failed or unexpected request.

##### `x-request-id`

**string · required**

The X-Request-Id you sent, echoed when it is a valid ID. Otherwise, the Engine request ID.

```json
{
  "fields": {
    "environment": {
      "type": "text",
      "status": "ready",
      "invalid_values": 0
    },
    "severity": {
      "type": "number",
      "status": "indexing",
      "invalid_values": 0
    }
  }
}
```

#### Response fields

##### `fields`

**map<string, object> · required**

Map of metadata key to the field. Only these keys can be used in a filter.

###### `fields[key].invalid_values`

**integer · required**

At least this many stored values do not fit the type, counted on a sample of the indexed files. They are stored, but no filter matches them.

###### `fields[key].status`

**string · required**

ready, or indexing while the index of this field is rebuilt after a change.

- `ready`: Filters read the current index of this field.
- `indexing`: The index of this field is being rebuilt. Filters read the old index.

###### `fields[key].type`

**string · required**

How filters read the values of this field.

- `text`: Text. A number or a boolean is read as its JSON text. Compares in byte order.
- `number`: A number, or a string that holds a plain decimal number.
- `time`: An RFC 3339 date or date-time. Compares instants, so time zone offsets count.
- `bool`: true or false, or the string "true" or "false".

### 202 · Reindex accepted

The field list changed. The response is the job that rebuilds the metadata index.

Content type: `application/json`.

#### Response headers

##### `x-engine-request-id`

**string · required**

The Engine request ID. Retain it when investigating a failed or unexpected request.

##### `x-request-id`

**string · required**

The X-Request-Id you sent, echoed when it is a valid ID. Otherwise, the Engine request ID.

```json
{
  "id": "job_01K6Q6N7D8E9F0G1H2J3K4M5N6",
  "type": "reindex_metadata",
  "status": "running",
  "namespace": "acme",
  "collection": "incident-logs",
  "error": null,
  "created_at": "2026-10-06T10:00:00Z",
  "updated_at": "2026-10-06T10:00:00Z"
}
```

#### Response fields

##### `collection`

**string · optional · nullable**

Collection name when this job belongs to a collection. Otherwise omitted.

##### `created_at`

**string (date-time) · required**

Time the resource was created, as an ISO 8601 UTC timestamp.

##### `error`

**object · required · nullable**

Failure details, or null when no failure is recorded.

###### `error.code`

**string · required**

Machine-readable reason for the failure. Use this value for program logic and message for display or diagnostics.

###### `error.message`

**string · required**

Human-readable explanation of the failure. Do not parse this text to decide how to retry.

##### `file_id`

**string · optional · nullable**

File ID when this job acts on one file. Otherwise omitted.

##### `id`

**string · required**

Immutable job ID with the job_ prefix. Use it to read the current state.

##### `namespace`

**string · optional · nullable**

Namespace name when this job belongs to a namespace.

##### `status`

**string · required**

Current state of the asynchronous work. succeeded, failed, and canceled are terminal states.

- `queued`: Accepted and waiting to start.
- `running`: Work is in progress.
- `succeeded`: Work completed successfully.
- `failed`: Work ended with an error.
- `canceled`: Work ended after cancellation.

##### `type`

**string · required**

Kind of work accepted by the API.

- `index_file`: Index a new or replacement file.
- `delete_file`: Remove a file and clean its derived data.
- `reindex_collection`: Rebuild the collection’s derived data.
- `delete_collection`: Remove a collection and its derived data.
- `delete_namespace`: Remove a namespace and its collections.
- `apply_access_rule`: Apply changed governing rules to affected files.
- `reindex_metadata`: Rebuild the metadata index after a change of the metadata fields.

##### `updated_at`

**string (date-time) · required**

Time the resource last changed, as an ISO 8601 UTC timestamp.

## Errors

[Error format and retry guidance](/engine/reference/errors.md).

### 400 · `invalid_request`

A field, path, parameter, or conditional request rule is invalid.

Correct the request. Unknown fields are rejected.

```json
{
  "error": {
    "code": "invalid_request",
    "message": "A field, path, parameter, or conditional request rule is invalid.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 401 · `unauthenticated`

The API key is missing, invalid, or revoked.

Send an active key in Authorization: Bearer or X-API-Key.

```json
{
  "error": {
    "code": "unauthenticated",
    "message": "The API key is missing, invalid, or revoked.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 403 · `forbidden`

The key can see the resource but lacks permission for this operation.

Use a key with the required action or scope kind.

```json
{
  "error": {
    "code": "forbidden",
    "message": "The key can see the resource but lacks permission for this operation.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 404 · `not_found`

The resource is absent, deleted, or outside this key’s scope.

Check the identifier and the key’s namespace and collection scope.

```json
{
  "error": {
    "code": "not_found",
    "message": "The resource is absent, deleted, or outside this key’s scope.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 409 · `operation_in_progress`

An unfinished operation conflicts with this request.

Inspect the existing job and wait for its completion event before retrying.

```json
{
  "error": {
    "code": "operation_in_progress",
    "message": "An unfinished operation conflicts with this request.",
    "request_id": "req_example",
    "retryable": true,
    "details": {}
  }
}
```

### 413 · `request_too_large`

The JSON body exceeds the route limit: 6,291,456 bytes on :answer and research, 4,194,304 bytes on :search and :read-spans, and 1,048,576 bytes elsewhere.

Reduce the JSON body. Use upload or a URI source for larger file content.

```json
{
  "error": {
    "code": "request_too_large",
    "message": "The JSON body exceeds the route limit: 6,291,456 bytes on :answer and research, 4,194,304 bytes on :search and :read-spans, and 1,048,576 bytes elsewhere.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 503 · `temporarily_unavailable`

A dependency, cluster readiness condition, or capacity limit prevents this operation.

Inspect retryable and details. Retry only when permitted, preserving the idempotency key for the same write.

```json
{
  "error": {
    "code": "temporarily_unavailable",
    "message": "A dependency, cluster readiness condition, or capacity limit prevents this operation.",
    "request_id": "req_example",
    "retryable": true,
    "details": {}
  }
}
```

### 500 · `internal_error`

An unexpected server failure prevented this request from completing.

Retain request_id for investigation. Follow retryable before retrying a write.

```json
{
  "error": {
    "code": "internal_error",
    "message": "An unexpected server failure prevented this request from completing.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

## Other request languages

### cURL

```bash
curl -sS -X PATCH "$GRAPHON_ENGINE_URL/namespaces/acme/collections/incident-logs/metadata-fields" \
  -H "Authorization: Bearer $GRAPHON_ENGINE_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "fields": {
    "environment": {
      "type": "text"
    },
    "severity": {
      "type": "number"
    }
  }
}'
```

### Python

```python
import json
import os
import urllib.request

request = urllib.request.Request(
    os.environ["GRAPHON_ENGINE_URL"] + "/namespaces/acme/collections/incident-logs/metadata-fields",
    data=json.dumps({"fields": {"environment": {"type": "text"}, "severity": {"type": "number"}}}).encode("utf-8"),
    headers={
        "Authorization": "Bearer " + os.environ["GRAPHON_ENGINE_API_KEY"],
        "Content-Type": "application/json",
    },
    method="PATCH",
)
with urllib.request.urlopen(request) as response:
    print(response.read().decode())
```

### JavaScript

```javascript
const response = await fetch(process.env.GRAPHON_ENGINE_URL + "/namespaces/acme/collections/incident-logs/metadata-fields", {
  method: "PATCH",
  headers: {
    "Authorization": `Bearer ${process.env.GRAPHON_ENGINE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"fields":{"environment":{"type":"text"},"severity":{"type":"number"}}}),
});
console.log(response.status, await response.text());
```

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
