> For the complete documentation index, see [llms.txt](https://docs.truedat.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.truedat.io/v8.12/api-integrations/link-manager-apis/relations.md).

# Relations

## List all relations

> Returns relations visible to the current caller, optionally filtered by status.\
> \
> \*\*Permissions:\*\* Visibility is checked \*\*only on the source side\*\* of each relation; the target's permissions are not independently evaluated.\
> \- When the source is a \*\*business concept\*\*, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\
> &#x20; \- \*\*'View published business concepts'\*\*\
> &#x20; \- \*\*'View draft business concepts'\*\*\
> &#x20; \- \*\*'View deprecated business concepts'\*\*\
> &#x20; \- \*\*'View versioned business concepts'\*\*\
> &#x20; \- \*\*'View rejected business concepts'\*\*\
> &#x20; \- \*\*'View business concepts pending approval'\*\*\
> &#x20; When the concept is confidential, the caller must additionally hold \*\*'Manage confidential business concepts'\*\* on the concept's domains.\
> \- When the source is an \*\*ingest\*\*, the caller must hold at least one of the following:\
> &#x20; \- \*\*'View published ingests'\*\*\
> &#x20; \- \*\*'View draft ingests'\*\*\
> &#x20; \- \*\*'View deprecated ingests'\*\*\
> &#x20; \- \*\*'View versioned ingests'\*\*\
> &#x20; \- \*\*'View rejected ingests'\*\*\
> &#x20; \- \*\*'View ingests pending approval'\*\*\
> \- When the source is a \*\*data structure\*\*, no permission clause applies and the relation is filtered out.\
> The status-sensitive permission is generic: any of the listed view permissions grants access, without matching the resource's actual current status.\
> \
> \*\*Query parameter:\*\*\
> \- \`status\` (optional, string) – Default: \`'approved'\`. Includes relations whose \`status\` column is \`NULL\` (treated as approved). Use \`'nil'\` to filter only relations without an explicit status.\
> \
> The response includes hypermedia metadata for navigation and related actions. No pagination is applied; all matching visible relations are returned.<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations":{"get":{"description":"Returns relations visible to the current caller, optionally filtered by status.\n\n**Permissions:** Visibility is checked **only on the source side** of each relation; the target's permissions are not independently evaluated.\n- When the source is a **business concept**, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\n  - **'View published business concepts'**\n  - **'View draft business concepts'**\n  - **'View deprecated business concepts'**\n  - **'View versioned business concepts'**\n  - **'View rejected business concepts'**\n  - **'View business concepts pending approval'**\n  When the concept is confidential, the caller must additionally hold **'Manage confidential business concepts'** on the concept's domains.\n- When the source is an **ingest**, the caller must hold at least one of the following:\n  - **'View published ingests'**\n  - **'View draft ingests'**\n  - **'View deprecated ingests'**\n  - **'View versioned ingests'**\n  - **'View rejected ingests'**\n  - **'View ingests pending approval'**\n- When the source is a **data structure**, no permission clause applies and the relation is filtered out.\nThe status-sensitive permission is generic: any of the listed view permissions grants access, without matching the resource's actual current status.\n\n**Query parameter:**\n- `status` (optional, string) – Default: `'approved'`. Includes relations whose `status` column is `NULL` (treated as approved). Use `'nil'` to filter only relations without an explicit status.\n\nThe response includes hypermedia metadata for navigation and related actions. No pagination is applied; all matching visible relations are returned.\n","operationId":"TdLmWeb.RelationController.index","parameters":[{"description":"Filter by status. Default: 'approved'","in":"query","name":"status","required":false,"schema":{"enum":["approved","pending","rejected","nil"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationListResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"List all relations","tags":["Relations"]}}},"components":{"schemas":{"RelationListResponse":{"additionalProperties":false,"properties":{"_actions":{"additionalProperties":{"properties":{"href":{"description":"Action URL","type":"string"},"input":{"additionalProperties":true,"description":"Expected input data","type":"object"},"method":{"description":"HTTP method","type":"string"}},"required":["href","method"],"type":"object"},"description":"Available actions (hypermedia)","type":"object"},"data":{"description":"List of relations","items":{"$ref":"#/components/schemas/RelationResponse"},"type":"array"},"hypermedia":{"additionalProperties":true,"description":"Hypermedia data for navigation","nullable":true,"type":"object"}},"required":["data"],"title":"RelationListResponse","type":"object"},"RelationResponse":{"additionalProperties":false,"properties":{"context":{"additionalProperties":true,"description":"Additional context for the relation","type":"object"},"deleted_at":{"description":"Soft deletion timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_at":{"description":"Disable timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_reason":{"description":"Disable reason","nullable":true,"type":"string"},"id":{"description":"Relation ID","type":"integer"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"origin":{"description":"Relation origin","nullable":true,"type":"string"},"source_id":{"description":"Source resource ID","type":"integer"},"source_type":{"description":"Source resource type","type":"string"},"status":{"description":"Relation status (nil, approved, pending, rejected)","nullable":true,"type":"string"},"tag":{"$ref":"#/components/schemas/TagOrNull"},"tag_id":{"description":"Associated tag ID","nullable":true,"type":"integer"},"tag_type":{"description":"Tag type (derived from tag.value.type)","nullable":true,"type":"string"},"tags":{"description":"List of associated tags (legacy)","items":{"$ref":"#/components/schemas/TagObject"},"type":"array"},"target_id":{"description":"Target resource ID","type":"integer"},"target_type":{"description":"Target resource type","type":"string"},"updated_at":{"description":"Update timestamp","format":"date-time","type":"string"}},"required":["id","source_id","source_type","target_id","target_type","context","updated_at","inserted_at"],"title":"RelationResponse","type":"object"},"TagOrNull":{"additionalProperties":false,"nullable":true,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagOrNull","type":"object"},"TagValue":{"additionalProperties":true,"description":"Dynamic value of a tag","properties":{"expandable":{"description":"Optional expandable flag","nullable":true,"type":"string"},"target_type":{"description":"Target resource type","type":"string"},"type":{"description":"Tag type","type":"string"}},"required":["target_type","type"],"title":"TagValue","type":"object"},"TagObject":{"additionalProperties":false,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagObject","type":"object"},"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```

## Create a new relation

> Creates a new relation between two resources. The \`source\_type\` must be either 'business\_concept' or 'ingest'; 'data\_structure' is not permitted as a source but it may be the target.\
> \
> \*\*Request body\*\*:\
> \- Wrap fields inside a top-level \`relation\` object.\
> \- \*\*Required\*\*: \`source\_id\`, \`source\_type\`, \`target\_id\`, \`target\_type\`.\
> \- \*\*Optional\*\*:\
> &#x20; \- \`context\` (object): additional metadata; defaults to \`%{}\`.\
> &#x20; \- \`tag\_ids\` (array of integers): associates a tag; only the first ID is used (\`tag\_id\` is derived in the controller).\
> &#x20; \- \`origin\` (string, nullable): relation origin; schema default is \`nil\`.\
> &#x20; \- \`status\` (string, nullable): \*\*default is \`nil\`\*\*. On create, only \`'pending'\` is accepted besides \`null\`/omission. Values \`'approved'\` and \`'rejected'\` cannot be set at creation; use \`POST /api/relations/status\` to transition a pending relation.\
> \
> \*\*Permissions\*\*\
> The permission required depends on the \*\*source resource type\*\*:\
> \- If \`source\_type\` is \`'business\_concept'\`: requires \`Manage business concept links\` permission.\
> \- If \`source\_type\` is \`'ingest'\`: requires \`Manage ingest relations\` permission.\
> \
> The system also validates that the target resource exists and is accessible. The response includes a \`Location\` header pointing to the created relation.<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations":{"post":{"description":"Creates a new relation between two resources. The `source_type` must be either 'business_concept' or 'ingest'; 'data_structure' is not permitted as a source but it may be the target.\n\n**Request body**:\n- Wrap fields inside a top-level `relation` object.\n- **Required**: `source_id`, `source_type`, `target_id`, `target_type`.\n- **Optional**:\n  - `context` (object): additional metadata; defaults to `%{}`.\n  - `tag_ids` (array of integers): associates a tag; only the first ID is used (`tag_id` is derived in the controller).\n  - `origin` (string, nullable): relation origin; schema default is `nil`.\n  - `status` (string, nullable): **default is `nil`**. On create, only `'pending'` is accepted besides `null`/omission. Values `'approved'` and `'rejected'` cannot be set at creation; use `POST /api/relations/status` to transition a pending relation.\n\n**Permissions**\nThe permission required depends on the **source resource type**:\n- If `source_type` is `'business_concept'`: requires `Manage business concept links` permission.\n- If `source_type` is `'ingest'`: requires `Manage ingest relations` permission.\n\nThe system also validates that the target resource exists and is accessible. The response includes a `Location` header pointing to the created relation.\n","operationId":"TdLmWeb.RelationController.create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationRequest"}}},"description":"Relation","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationShowResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmBadRequestResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnprocessableEntityResponse"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Create a new relation","tags":["Relations"]}}},"components":{"schemas":{"RelationRequest":{"additionalProperties":false,"properties":{"relation":{"additionalProperties":false,"description":"Relation data","properties":{"context":{"additionalProperties":true,"description":"Additional context for the relation","nullable":true,"type":"object"},"origin":{"description":"Relation origin (defaults to nil)","nullable":true,"type":"string"},"source_id":{"description":"Source resource ID","type":"integer"},"source_type":{"description":"Source resource type","enum":["business_concept","data_field","data_structure","ingest","implementation_ref","quality_control"],"type":"string"},"status":{"description":"Relation status (only 'pending' or nil)","enum":["pending"],"nullable":true,"type":"string"},"tag_ids":{"description":"List of tag IDs (currently only one is supported)","items":{"type":"integer"},"type":"array"},"tags":{"description":"Legacy field for compatibility (not used in creation)","items":{"$ref":"#/components/schemas/TagObject"},"type":"array"},"target_id":{"description":"Target resource ID","type":"integer"},"target_type":{"description":"Target resource type","enum":["business_concept","data_field","data_structure","ingest","implementation_ref","quality_control"],"type":"string"}},"required":["source_id","source_type","target_id","target_type"],"type":"object"}},"required":["relation"],"title":"RelationRequest","type":"object"},"TagObject":{"additionalProperties":false,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagObject","type":"object"},"TagValue":{"additionalProperties":true,"description":"Dynamic value of a tag","properties":{"expandable":{"description":"Optional expandable flag","nullable":true,"type":"string"},"target_type":{"description":"Target resource type","type":"string"},"type":{"description":"Tag type","type":"string"}},"required":["target_type","type"],"title":"TagValue","type":"object"},"RelationShowResponse":{"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/RelationResponse"}},"required":["data"],"title":"RelationShowResponse","type":"object"},"RelationResponse":{"additionalProperties":false,"properties":{"context":{"additionalProperties":true,"description":"Additional context for the relation","type":"object"},"deleted_at":{"description":"Soft deletion timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_at":{"description":"Disable timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_reason":{"description":"Disable reason","nullable":true,"type":"string"},"id":{"description":"Relation ID","type":"integer"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"origin":{"description":"Relation origin","nullable":true,"type":"string"},"source_id":{"description":"Source resource ID","type":"integer"},"source_type":{"description":"Source resource type","type":"string"},"status":{"description":"Relation status (nil, approved, pending, rejected)","nullable":true,"type":"string"},"tag":{"$ref":"#/components/schemas/TagOrNull"},"tag_id":{"description":"Associated tag ID","nullable":true,"type":"integer"},"tag_type":{"description":"Tag type (derived from tag.value.type)","nullable":true,"type":"string"},"tags":{"description":"List of associated tags (legacy)","items":{"$ref":"#/components/schemas/TagObject"},"type":"array"},"target_id":{"description":"Target resource ID","type":"integer"},"target_type":{"description":"Target resource type","type":"string"},"updated_at":{"description":"Update timestamp","format":"date-time","type":"string"}},"required":["id","source_id","source_type","target_id","target_type","context","updated_at","inserted_at"],"title":"RelationResponse","type":"object"},"TagOrNull":{"additionalProperties":false,"nullable":true,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagOrNull","type":"object"},"TdLmBadRequestResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmBadRequestResponse","type":"object"},"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmUnprocessableEntityResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnprocessableEntityResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```

## Hard delete multiple relations

> Permanently removes multiple relations from the database based on a list of IDs. This operation is irreversible.\
> \
> \*\*Response parameters\*\*:\
> \- \`deleted\`: IDs successfully removed.\
> \- \`errors\`: error messages for IDs that could not be deleted (already deleted or user's permission failure). May be empty.\
> \
> Requires administrative privileges (\*\*administrator or service account\*\*).<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations/hard_delete":{"delete":{"description":"Permanently removes multiple relations from the database based on a list of IDs. This operation is irreversible.\n\n**Response parameters**:\n- `deleted`: IDs successfully removed.\n- `errors`: error messages for IDs that could not be deleted (already deleted or user's permission failure). May be empty.\n\nRequires administrative privileges (**administrator or service account**).\n","operationId":"TdLmWeb.RelationController.hard_delete","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HardDeleteRequest"}}},"description":"IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HardDeleteResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnprocessableEntityResponse"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Hard delete multiple relations","tags":["Relations"]}}},"components":{"schemas":{"HardDeleteRequest":{"additionalProperties":false,"properties":{"ids":{"description":"List of relation IDs to permanently delete","items":{"type":"integer"},"type":"array"}},"required":["ids"],"title":"HardDeleteRequest","type":"object"},"HardDeleteResponse":{"additionalProperties":false,"properties":{"data":{"additionalProperties":false,"properties":{"deleted":{"description":"IDs of successfully deleted relations","items":{"type":"integer"},"type":"array"},"errors":{"description":"Errors encountered during deletion","items":{"type":"string"},"type":"array"}},"required":["deleted"],"type":"object"}},"required":["data"],"title":"HardDeleteResponse","type":"object"},"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmUnprocessableEntityResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnprocessableEntityResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```

## Search relations

> Searches relations directly in the database (not the Elasticsearch index; use \`POST /api/relations/index\_search\` for indexed search).\
> \
> \*\*Two request modes:\*\*\
> 1\. \*\*Resource-based mode\*\* – the three fields below must be provided together:\
> &#x20;  \- \`resource\_id\` (integer) – ID of the anchor resource.\
> &#x20;  \- \`resource\_type\` (string) – Type of the anchor resource. One of 'business\_concept', 'ingest', or 'data\_structure'.\
> &#x20;  \- \`related\_to\_type\` (string) – Type of the related resource on the opposite side of the relation.\
> &#x20;  The query runs in both directions (anchor as source and anchor as target). However, \*\*only relations whose source is a business concept or an ingest are returned\*\*. Relations whose source is a data structure are silently filtered out, so for a data structure anchor only the direction where the anchor is the target is effective.\
> 2\. \*\*General mode\*\* – any combination of \`source\_id\`, \`source\_type\`, \`target\_id\`, \`target\_type\`, \`status\`, and \`tag\_id\`. Do not mix this mode with the three resource-based fields above.\
> \
> \*\*Status filter (both modes):\*\*\
> \- \`status\` (string, optional) – Default: \`'approved'\`. When the effective status is \`'approved'\`, relations whose \`status\` column is \`NULL\` are also returned (treated as approved). Use \`'nil'\` to filter only relations without an explicit status.\
> \
> \*\*Permissions:\*\* Visibility is checked \*\*only on the source side\*\* of each relation; the target's permissions are not independently evaluated.\
> \- When the source is a \*\*business concept\*\*, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\
> &#x20; \- \*\*'View published business concepts'\*\*\
> &#x20; \- \*\*'View draft business concepts'\*\*\
> &#x20; \- \*\*'View deprecated business concepts'\*\*\
> &#x20; \- \*\*'View versioned business concepts'\*\*\
> &#x20; \- \*\*'View rejected business concepts'\*\*\
> &#x20; \- \*\*'View business concepts pending approval'\*\*\
> &#x20; Additionally, when the concept is confidential, the caller must hold \*\*'Manage confidential business concepts'\*\* on the concept's domains.\
> \- When the source is an \*\*ingest\*\*, the caller must hold at least one of the following on the ingest:\
> &#x20; \- \*\*'View published ingests'\*\*\
> &#x20; \- \*\*'View draft ingests'\*\*\
> &#x20; \- \*\*'View deprecated ingests'\*\*\
> &#x20; \- \*\*'View versioned ingests'\*\*\
> &#x20; \- \*\*'View rejected ingests'\*\*\
> &#x20; \- \*\*'View ingests pending approval'\*\*\
> \- When the source is a \*\*data structure\*\*, no permission clause applies and the relation is filtered out of the result.\
> The status-sensitive permission is generic: any of the listed view permissions grants access, without matching the resource's actual current status.\
> \
> \*\*Response:\*\*\
> \- \`data\` – array of relation objects with \`id\`, \`source\_id\`, \`source\_type\`, \`target\_id\`, \`target\_type\`, \`context\`, \`status\`, \`origin\`, \`tag\`/\`tags\`, \`tag\_id\`, \`tag\_type\`, and timestamps (\`inserted\_at\`, \`updated\_at\`, \`deleted\_at\`, \`disabled\_at\`, \`disabled\_reason\`).\
> \- \`\_actions\` / \`hypermedia\` – navigation metadata keyed to the anchor resource.\
> \
> When \`related\_to\_type\` is 'business\_concept' or 'ingest', the corresponding side of the relation's \`context\` is enriched with the cached \`name\` and \`version\_id\`. When \`related\_to\_type\` is 'data\_structure', no enrichment is applied.\
> \
> The search does not paginate; all matching visible relations are returned in a single response.<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations/search":{"post":{"description":"Searches relations directly in the database (not the Elasticsearch index; use `POST /api/relations/index_search` for indexed search).\n\n**Two request modes:**\n1. **Resource-based mode** – the three fields below must be provided together:\n   - `resource_id` (integer) – ID of the anchor resource.\n   - `resource_type` (string) – Type of the anchor resource. One of 'business_concept', 'ingest', or 'data_structure'.\n   - `related_to_type` (string) – Type of the related resource on the opposite side of the relation.\n   The query runs in both directions (anchor as source and anchor as target). However, **only relations whose source is a business concept or an ingest are returned**. Relations whose source is a data structure are silently filtered out, so for a data structure anchor only the direction where the anchor is the target is effective.\n2. **General mode** – any combination of `source_id`, `source_type`, `target_id`, `target_type`, `status`, and `tag_id`. Do not mix this mode with the three resource-based fields above.\n\n**Status filter (both modes):**\n- `status` (string, optional) – Default: `'approved'`. When the effective status is `'approved'`, relations whose `status` column is `NULL` are also returned (treated as approved). Use `'nil'` to filter only relations without an explicit status.\n\n**Permissions:** Visibility is checked **only on the source side** of each relation; the target's permissions are not independently evaluated.\n- When the source is a **business concept**, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\n  - **'View published business concepts'**\n  - **'View draft business concepts'**\n  - **'View deprecated business concepts'**\n  - **'View versioned business concepts'**\n  - **'View rejected business concepts'**\n  - **'View business concepts pending approval'**\n  Additionally, when the concept is confidential, the caller must hold **'Manage confidential business concepts'** on the concept's domains.\n- When the source is an **ingest**, the caller must hold at least one of the following on the ingest:\n  - **'View published ingests'**\n  - **'View draft ingests'**\n  - **'View deprecated ingests'**\n  - **'View versioned ingests'**\n  - **'View rejected ingests'**\n  - **'View ingests pending approval'**\n- When the source is a **data structure**, no permission clause applies and the relation is filtered out of the result.\nThe status-sensitive permission is generic: any of the listed view permissions grants access, without matching the resource's actual current status.\n\n**Response:**\n- `data` – array of relation objects with `id`, `source_id`, `source_type`, `target_id`, `target_type`, `context`, `status`, `origin`, `tag`/`tags`, `tag_id`, `tag_type`, and timestamps (`inserted_at`, `updated_at`, `deleted_at`, `disabled_at`, `disabled_reason`).\n- `_actions` / `hypermedia` – navigation metadata keyed to the anchor resource.\n\nWhen `related_to_type` is 'business_concept' or 'ingest', the corresponding side of the relation's `context` is enriched with the cached `name` and `version_id`. When `related_to_type` is 'data_structure', no enrichment is applied.\n\nThe search does not paginate; all matching visible relations are returned in a single response.\n","operationId":"TdLmWeb.RelationController.search","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationSearchRequest"}}},"description":"Search parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationListResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Search relations","tags":["Relations"]}}},"components":{"schemas":{"RelationSearchRequest":{"additionalProperties":false,"properties":{"related_to_type":{"description":"Related resource type (required for resource-based search)","type":"string"},"resource_id":{"description":"Root resource ID for search (required for resource-based search)","type":"integer"},"resource_type":{"description":"Root resource type (required for resource-based search)","type":"string"},"source_id":{"description":"Source ID (alternative search)","type":"integer"},"source_type":{"description":"Source type (alternative search)","type":"string"},"status":{"description":"Status filter (defaults to 'approved')","enum":["approved","pending","rejected","nil"],"nullable":true,"type":"string"}},"title":"RelationSearchRequest","type":"object"},"RelationListResponse":{"additionalProperties":false,"properties":{"_actions":{"additionalProperties":{"properties":{"href":{"description":"Action URL","type":"string"},"input":{"additionalProperties":true,"description":"Expected input data","type":"object"},"method":{"description":"HTTP method","type":"string"}},"required":["href","method"],"type":"object"},"description":"Available actions (hypermedia)","type":"object"},"data":{"description":"List of relations","items":{"$ref":"#/components/schemas/RelationResponse"},"type":"array"},"hypermedia":{"additionalProperties":true,"description":"Hypermedia data for navigation","nullable":true,"type":"object"}},"required":["data"],"title":"RelationListResponse","type":"object"},"RelationResponse":{"additionalProperties":false,"properties":{"context":{"additionalProperties":true,"description":"Additional context for the relation","type":"object"},"deleted_at":{"description":"Soft deletion timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_at":{"description":"Disable timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_reason":{"description":"Disable reason","nullable":true,"type":"string"},"id":{"description":"Relation ID","type":"integer"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"origin":{"description":"Relation origin","nullable":true,"type":"string"},"source_id":{"description":"Source resource ID","type":"integer"},"source_type":{"description":"Source resource type","type":"string"},"status":{"description":"Relation status (nil, approved, pending, rejected)","nullable":true,"type":"string"},"tag":{"$ref":"#/components/schemas/TagOrNull"},"tag_id":{"description":"Associated tag ID","nullable":true,"type":"integer"},"tag_type":{"description":"Tag type (derived from tag.value.type)","nullable":true,"type":"string"},"tags":{"description":"List of associated tags (legacy)","items":{"$ref":"#/components/schemas/TagObject"},"type":"array"},"target_id":{"description":"Target resource ID","type":"integer"},"target_type":{"description":"Target resource type","type":"string"},"updated_at":{"description":"Update timestamp","format":"date-time","type":"string"}},"required":["id","source_id","source_type","target_id","target_type","context","updated_at","inserted_at"],"title":"RelationResponse","type":"object"},"TagOrNull":{"additionalProperties":false,"nullable":true,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagOrNull","type":"object"},"TagValue":{"additionalProperties":true,"description":"Dynamic value of a tag","properties":{"expandable":{"description":"Optional expandable flag","nullable":true,"type":"string"},"target_type":{"description":"Target resource type","type":"string"},"type":{"description":"Tag type","type":"string"}},"required":["target_type","type"],"title":"TagValue","type":"object"},"TagObject":{"additionalProperties":false,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagObject","type":"object"},"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```

## Get a relation by ID

> &#x20; Retrieves a single relation by ID.\
> \
> \*\*Permissions:\*\* Visibility is checked \*\*only on the source side\*\* of the relation; the target's permissions are not independently evaluated.\
> \- When the source is a \*\*business concept\*\*, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\
> &#x20; \- \*\*'View published business concepts'\*\*\
> &#x20; \- \*\*'View draft business concepts'\*\*\
> &#x20; \- \*\*'View deprecated business concepts'\*\*\
> &#x20; \- \*\*'View versioned business concepts'\*\*\
> &#x20; \- \*\*'View rejected business concepts'\*\*\
> &#x20; \- \*\*'View business concepts pending approval'\*\*\
> &#x20; When the concept is confidential, the caller must additionally hold \*\*'Manage confidential business concepts'\*\* on the concept's domains.\
> \- When the source is an \*\*ingest\*\*, the caller must hold at least one of the following:\
> &#x20; \- \*\*'View published ingests'\*\*\
> &#x20; \- \*\*'View draft ingests'\*\*\
> &#x20; \- \*\*'View deprecated ingests'\*\*\
> &#x20; \- \*\*'View versioned ingests'\*\*\
> &#x20; \- \*\*'View rejected ingests'\*\*\
> &#x20; \- \*\*'View ingests pending approval'\*\*\
> \- When the source is a \*\*data structure\*\*, no permission clause applies and the relation is filtered out (even when requested by ID).\
> \
> \*\*Response:\*\* Object with \`id\`, \`source\_id\`, \`source\_type\`, \`target\_id\`, \`target\_type\`, \`context\`, \`status\`, \`origin\`, \`tag\`/\`tags\`, \`tag\_id\`, \`tag\_type\`, and timestamps.<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations/{id}":{"get":{"description":"  Retrieves a single relation by ID.\n\n**Permissions:** Visibility is checked **only on the source side** of the relation; the target's permissions are not independently evaluated.\n- When the source is a **business concept**, the caller must hold at least one of the following on the concept's domains (own domain plus shared domains):\n  - **'View published business concepts'**\n  - **'View draft business concepts'**\n  - **'View deprecated business concepts'**\n  - **'View versioned business concepts'**\n  - **'View rejected business concepts'**\n  - **'View business concepts pending approval'**\n  When the concept is confidential, the caller must additionally hold **'Manage confidential business concepts'** on the concept's domains.\n- When the source is an **ingest**, the caller must hold at least one of the following:\n  - **'View published ingests'**\n  - **'View draft ingests'**\n  - **'View deprecated ingests'**\n  - **'View versioned ingests'**\n  - **'View rejected ingests'**\n  - **'View ingests pending approval'**\n- When the source is a **data structure**, no permission clause applies and the relation is filtered out (even when requested by ID).\n\n**Response:** Object with `id`, `source_id`, `source_type`, `target_id`, `target_type`, `context`, `status`, `origin`, `tag`/`tags`, `tag_id`, `tag_type`, and timestamps.\n","operationId":"TdLmWeb.RelationController.show","parameters":[{"description":"Relation ID","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationShowResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmNotFoundResponse"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Get a relation by ID","tags":["Relations"]}}},"components":{"schemas":{"RelationShowResponse":{"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/RelationResponse"}},"required":["data"],"title":"RelationShowResponse","type":"object"},"RelationResponse":{"additionalProperties":false,"properties":{"context":{"additionalProperties":true,"description":"Additional context for the relation","type":"object"},"deleted_at":{"description":"Soft deletion timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_at":{"description":"Disable timestamp","format":"date-time","nullable":true,"type":"string"},"disabled_reason":{"description":"Disable reason","nullable":true,"type":"string"},"id":{"description":"Relation ID","type":"integer"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"origin":{"description":"Relation origin","nullable":true,"type":"string"},"source_id":{"description":"Source resource ID","type":"integer"},"source_type":{"description":"Source resource type","type":"string"},"status":{"description":"Relation status (nil, approved, pending, rejected)","nullable":true,"type":"string"},"tag":{"$ref":"#/components/schemas/TagOrNull"},"tag_id":{"description":"Associated tag ID","nullable":true,"type":"integer"},"tag_type":{"description":"Tag type (derived from tag.value.type)","nullable":true,"type":"string"},"tags":{"description":"List of associated tags (legacy)","items":{"$ref":"#/components/schemas/TagObject"},"type":"array"},"target_id":{"description":"Target resource ID","type":"integer"},"target_type":{"description":"Target resource type","type":"string"},"updated_at":{"description":"Update timestamp","format":"date-time","type":"string"}},"required":["id","source_id","source_type","target_id","target_type","context","updated_at","inserted_at"],"title":"RelationResponse","type":"object"},"TagOrNull":{"additionalProperties":false,"nullable":true,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagOrNull","type":"object"},"TagValue":{"additionalProperties":true,"description":"Dynamic value of a tag","properties":{"expandable":{"description":"Optional expandable flag","nullable":true,"type":"string"},"target_type":{"description":"Target resource type","type":"string"},"type":{"description":"Tag type","type":"string"}},"required":["target_type","type"],"title":"TagValue","type":"object"},"TagObject":{"additionalProperties":false,"properties":{"id":{"description":"Tag ID","type":"integer"},"value":{"$ref":"#/components/schemas/TagValue"}},"required":["id","value"],"title":"TagObject","type":"object"},"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmNotFoundResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmNotFoundResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```

## Soft delete a relation

> Soft-deletes a relation by setting \`deleted\_at\` without removing the database row. The relation remains for audit/history but is excluded from default database and index searches (unless explicitly included via search \`with\`/\`document\` parameters). The operation is reversible only by a database restoration; there is no public API to restore a soft-deleted relation.\
> \
> The \`source\_type\` must be either 'business\_concept' or 'ingest'; 'data\_structure' is not permitted as a source but it may be the target.\
> \
> \*\*Permissions\*\*\
> Requires permission to manage links on the \*\*source resource\*\* of the relation:\
> \- If the source is a business concept: \`Manage business concept links\` permission.\
> \- If the source is an ingest: \`Manage ingest relations\` permission.<br>

```json
{"openapi":"3.0.0","info":{"title":"td-lm","version":"Truedat 8.11.1"},"paths":{"/api/relations/{id}":{"delete":{"description":"Soft-deletes a relation by setting `deleted_at` without removing the database row. The relation remains for audit/history but is excluded from default database and index searches (unless explicitly included via search `with`/`document` parameters). The operation is reversible only by a database restoration; there is no public API to restore a soft-deleted relation.\n\nThe `source_type` must be either 'business_concept' or 'ingest'; 'data_structure' is not permitted as a source but it may be the target.\n\n**Permissions**\nRequires permission to manage links on the **source resource** of the relation:\n- If the source is a business concept: `Manage business concept links` permission.\n- If the source is an ingest: `Manage ingest relations` permission.\n","operationId":"TdLmWeb.RelationController.delete","parameters":[{"description":"Relation ID","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Relation deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmUnauthorizedResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmForbiddenResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmNotFoundResponse"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TdLmInternalServerErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Soft delete a relation","tags":["Relations"]}}},"components":{"schemas":{"TdLmUnauthorizedResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmUnauthorizedResponse","type":"object"},"TdLmForbiddenResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmForbiddenResponse","type":"object"},"TdLmNotFoundResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmNotFoundResponse","type":"object"},"TdLmInternalServerErrorResponse":{"properties":{"errors":{"properties":{"detail":{"type":"string"}},"type":"object"}},"title":"TdLmInternalServerErrorResponse","type":"object"}}}}
```
