> For the complete documentation index, see [llms.txt](https://developer.collibra.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.collibra.com/api/references/data-quality/data-egress.md).

# Data Egress

Bulk extraction of DQ data — jobs, monitors, and rules joined across topics and streamed (NDJSON or CSV) in a single pass for BI tools, data pipelines, and integrations.

## Export joined data across multiple DQ topics

> Streams the full result set of rows joined across an arbitrary\
> connected subset of the DQ topics (\`jobs\`, \`monitors\`, \`rules\`)\
> in a single pass for bulk extraction into BI tools, data pipelines,\
> and integrations.\
> \
> The request body is \*\*optional\*\*: POST with no body (or a body that\
> omits \`topics\`) to export all three topics — \`jobs\`, \`monitors\`,\
> \`rules\` — with every other default applied.\
> \
> \*\*Response format (content negotiation).\*\* The format is selected by\
> the \`Accept\` request header:\
> \- \`Accept: application/x-ndjson\` → newline-delimited JSON\
> &#x20; (\[JSON Lines]\(<https://jsonlines.org>)): one JSON object per line.\
> &#x20; Preferred for programmatic consumers — types are\
> &#x20; preserved (numbers stay numbers, \`null\` stays \`null\`) and rows can\
> &#x20; be parsed incrementally.\
> \- \`Accept: text/csv\` → CSV download. The header row is the qualified\
> &#x20; field names (e.g. \`rules.ruleName\`). List-typed fields\
> &#x20; (\`jobs.daysOfWeek\`, \`monitors.dimensionNames\`, \`rules.dimensionNames\`)\
> &#x20; render as pipe-delimited cells (\`Completeness|Accuracy\`) so\
> &#x20; consumers don't have to handle quoted-comma CSV.\
> \
> When \`Accept\` is absent or \`\*/\*\`, the server returns\
> \`application/x-ndjson\`; any other media type is rejected with\
> HTTP 406. Both formats stream the same rows in the same order; only\
> the encoding differs.\
> \
> \*\*Topics.\*\* \`JOBS\`, \`MONITORS\`, and \`RULES\` are mutually\
> joinable — any non-empty combination of them is valid. Quality\
> dimensions are not a topic: the names of the quality dimensions\
> assigned to a monitor (and to a rule — a rule is a \`RULE\`-type\
> monitor) are surfaced inline on the row as the\
> \`monitors.dimensionNames\` / \`rules.dimensionNames\` list field\
> (active assignments only; empty when none are assigned).\
> \
> To discover what topics can be joined call GET \`/egress/manifest\` first. Each topic's\
> \`joinsTo\` lists the other topics it can be joined to; your selected\
> \`topics\` are valid if they form a connected subgraph over those edges.\
> The manifest also lists each field's \`filterable\` flag and\
> \`allowedOperators\`, so a client can fully validate a request locally\
> before POSTing.\
> \
> \*\*Filters.\*\* Optional predicates in the body's \`filters\` array, \*\*ANDed\*\*\
> together (omit for no filtering beyond RBAC and the default window). Each\
> \`EgressFilter\` is a \`field\`, an \`op\`, and a value whose shape depends on\
> the operator:\
> \- \`value\` (a single scalar) for \`EQ\`, \`NE\`, \`LIKE\`, \`GT\`, \`GTE\`, \`LT\`, \`LTE\`\
> \- \`values\` (an array) for \`IN\`, \`NOT\_IN\`\
> \- neither for \`IS\_NULL\`, \`IS\_NOT\_NULL\`\
> \
> \`field\` is the qualified name \`\<topic>.\<apiName>\` (e.g. \`rules.ruleName\`)\
> and must belong to a \*\*selected\*\* topic; each field permits only a subset\
> of operators. Call \`GET /egress/manifest\` to discover the filterable\
> fields and their \`allowedOperators\`. A request fails with HTTP 400 if a\
> filter names an unknown field, uses an operator the field doesn't allow,\
> or references a field whose topic isn't in \`topics\`. Filtering on any\
> \`\*.updatedAt\` field also overrides the default time window (see below).\
> \
> \*\*Ordering.\*\* Custom sort keys are not currently a request parameter.\
> Rows are always returned ordered by \`\<granularity>.updatedAt\`\
> descending — the same field the default time window keys on (rules >\
> monitors > jobs) — followed by a unique tiebreaker for deterministic\
> streaming.\
> \
> \*\*Projection.\*\* is not currently a request parameter. Each row is a\
> key/value map containing all projectable fields of the selected\
> topics, in manifest order (fields marked \`optIn: true\` are excluded\
> unless explicitly enabled — see catalog assets below). Use\
> \`GET /egress/manifest\` to discover the supported topics, fields,\
> operators, and opt-in flags.\
> \
> \*\*Catalog assets (opt-in).\*\* Set \`includeCatalogAssets\` (query parameter\
> or request-body property — enrichment applies when either is \`true\`;\
> default \`false\`) to add, to each row, the DGC Catalog assets it maps to.\
> Three field groups are populated, all omitted when the flag is off:\
> \
> \- \*\*Table\*\* — \`jobs.tableCatalogAssetId\` / \`...DisplayName\` / \`...Type\`:\
> &#x20; the Catalog \`Table\` asset for the row's table. One per row.\
> \- \*\*Column\*\* — \`monitors.columnCatalogAsset\*\` and\
> &#x20; \`rules.columnCatalogAsset\*\`: the \`Column\` asset for the row's column\
> &#x20; (\`monitors.columnName\` / \`rules.ruleColumnName\`). One per row, or\
> &#x20; \`null\` when the row has no column scope (e.g. a dataset-level monitor).\
> \- \*\*Business Rule\*\* — \`monitors.businessRuleLinks\`: the \`Business Rule\`\
> &#x20; assets linked to the monitor, matched by identity (a rule surfaces here\
> &#x20; as its \`RULE\`-type monitor). Collapsed into one list of\
> &#x20; \`"\<assetId>::\<signifier>"\` entries, so a monitor linked to several rules\
> &#x20; stays one row (no row multiplication).\
> \
> Two query parameters trim the enrichment (both default \`false\`):\
> \`excludeColumnAssets\` omits the Column group; \`excludeRuleAssets\` omits\
> the Business Rule group. Both are no-ops unless \`includeCatalogAssets\`\
> is in effect.\
> \
> \*\*Default time window.\*\* When the request omits any \`\*.updatedAt\`\
> filter, the server injects a rolling window on the \`updatedAt\` of a\
> selected topic, anchored in the order monitors > rules > jobs.\
> Its length is the \`window\` query parameter in days, defaulting to 90.\
> To set an exact range instead, filter explicitly on any \`\*.updatedAt\`\
> field — the server suppresses the injected window (and ignores \`window\`)\
> once any such filter is present. The default-window contract is also\
> surfaced in \`defaultWindow\` on the manifest response.\
> \
> \*\*Permissions\*\*\
> \- \*\*Required:\*\* \`DATA\_QUALITY\` and \`DATA\_QUALITY\_JOB\_VIEW\`. Results are\
> &#x20; scoped to the jobs the caller can see.\
> \- \*\*Global bypass:\*\*\
> &#x20; \- \`DATA\_QUALITY\` and \`VIEW\_PERMISSIONS\_VIEW\_ALL\`\
> &#x20; \- \`DATA\_QUALITY\` and \`RESOURCE\_MANAGE\_ALL\`

```json
{"openapi":"3.0.3","info":{"title":"Data Quality Collibra API","version":"1.3.0"},"tags":[{"name":"Data Egress","description":"Bulk extraction of DQ data — jobs, monitors, and rules joined across topics and streamed (NDJSON or CSV) in a single pass for BI tools, data pipelines, and integrations."}],"servers":[{"description":"Data Quality API","url":"/rest/dq/1.0"}],"security":[{"basicAuth":[]},{"jwtAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"description":"Collibra REST API authentication using Basic Authentication.","type":"http","scheme":"basic"},"jwtAuth":{"description":"Collibra REST API authentication using JSON Web Token.","type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EgressRequest":{"type":"object","description":"Request body for `POST /egress/export`. Optional — omit the body (or\nomit `topics`) to export all three topics with defaults. Any `topics`\nyou do select must form a connected subgraph in the manifest's join graph.","properties":{"topics":{"type":"array","maxItems":16,"uniqueItems":true,"description":"Topics to include in the export. Omitted or empty → all three\n(`JOBS`, `MONITORS`, `RULES`). Today's surface exposes those three;\nthe upper bound has headroom so adding a new topic doesn't break clients.","items":{"$ref":"#/components/schemas/EgressTopic"}},"filters":{"type":"array","maxItems":100,"description":"Filter predicates ANDed together. Empty or omitted means no filtering.","items":{"$ref":"#/components/schemas/EgressFilter"}},"includeCatalogAssets":{"type":"boolean","default":false,"description":"Opt in to catalog-asset enrichment. May also be set via the\n`includeCatalogAssets` query parameter (useful on a body-less\nrequest); enrichment applies when either is `true`. When `true`, each\nrow is enriched with the DGC Catalog assets it maps to: the `Table`\nasset on `jobs`, the `Column` asset on `monitors`/`rules`, and the\ngoverning `Data Quality Rule` asset on `monitors`. See **Catalog\nassets** in the `POST /egress/export` description for the exact\nfields and the `excludeColumnAssets` / `excludeRuleAssets` switches.\n\nWhen `false` (default) no enrichment is performed and those fields\nare omitted — off by default because enrichment makes external\nround-trips to DGC. Note a monitor linked to several `Data Quality\nRule` assets emits one row per linked asset; `excludeRuleAssets`\nopts out of that group (and its row multiplication)."}}},"EgressTopic":{"type":"string","description":"Selectable topic for the data-egress export endpoint. Values follow\nthe platform-wide UPPER_SNAKE_CASE enum convention. Note that\nqualified field names in filters use the lowercase form\n(e.g. `rules.ruleName`); the qualified-name syntax is its own grammar\nand is intentionally distinct from the enum.","enum":["JOBS","MONITORS","RULES"]},"EgressFilter":{"type":"object","description":"Single filter predicate. Use `value` for `EQ`/`NE`/`LIKE`/`GTE`/`LTE`/`GT`/`LT`,\n`values` for `IN`/`NOT_IN`, and neither for `IS_NULL`/`IS_NOT_NULL`.","required":["field","op"],"properties":{"field":{"type":"string","description":"Qualified field name `<topic>.<apiName>`, e.g. `rules.ruleName`.","maxLength":128},"op":{"$ref":"#/components/schemas/EgressOperator"},"value":{"description":"Single value for unary operators. Send as a JSON scalar (string,\nnumber, integer, or boolean), or `null`. The server coerces the\nvalue to the field's declared type (string / integer / long /\ndouble / boolean / RFC 3339 timestamp / UUID) at validation time\nbefore binding into the SQL parameter. The schema is kept type-less\nrather than\nusing `oneOf` because OAS codegen wraps `oneOf` in a sealed\nwrapper that breaks the server's dynamic-coercion flow; the\nscalar-or-null constraint is enforced server-side."},"values":{"type":"array","description":"List of values for `IN` / `NOT_IN`. Each item follows the same\nscalar-or-null contract as `value` above and is coerced to the\nfield's declared type at validation time. Capped at 1000 items\nper request as a DoS guard; pageable surfaces should split\nlarger lists across multiple requests.","maxItems":1000,"items":{"description":"JSON scalar (string / number / integer / boolean) or `null`.\nSchema kept type-less for the same dynamic-coercion reason\nas the sibling `value` property."}}}},"EgressOperator":{"type":"string","description":"Filter operator. Each field declares its allowed operators in the\nmanifest; requesting an unsupported operator yields HTTP 400.\n\n`LIKE` exposes SQL `%` (zero-or-more chars) and `_` (single char)\nwildcards verbatim and is case-sensitive — the operator is a thin\nwrapper over the SQL `LIKE` predicate. Callers that want\ncase-insensitive matching or anchored prefix/suffix can express that\nwith the wildcards (`%foo%` for contains, `foo%` for prefix). The\nintentional SQL-flavoured shape mirrors the rest of the egress\nquery surface; consumers that need a higher-level abstraction can\nlayer it on the client.","enum":["EQ","NE","IN","NOT_IN","LIKE","GTE","LTE","GT","LT","IS_NULL","IS_NOT_NULL"]},"StandardErrorResponse":{"type":"object","description":"Error response returned by the Data Quality API.","required":["statusCode","errorCode","titleMessage","userMessage"],"properties":{"statusCode":{"type":"integer","description":"HTTP status code corresponding to the error."},"errorCode":{"type":"string","description":"Internal error code representing the specific error type."},"titleMessage":{"type":"string","description":"A brief title summarizing the error."},"userMessage":{"type":"string","description":"Detailed, user-friendly message explaining the error and possible remediation steps."}}}},"responses":{"BadRequest":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"Unauthorized":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"NotAcceptable":{"description":"Not Acceptable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"TooManyRequests":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}}}},"paths":{"/egress/export":{"post":{"tags":["Data Egress"],"summary":"Export joined data across multiple DQ topics","description":"Streams the full result set of rows joined across an arbitrary\nconnected subset of the DQ topics (`jobs`, `monitors`, `rules`)\nin a single pass for bulk extraction into BI tools, data pipelines,\nand integrations.\n\nThe request body is **optional**: POST with no body (or a body that\nomits `topics`) to export all three topics — `jobs`, `monitors`,\n`rules` — with every other default applied.\n\n**Response format (content negotiation).** The format is selected by\nthe `Accept` request header:\n- `Accept: application/x-ndjson` → newline-delimited JSON\n  ([JSON Lines](https://jsonlines.org)): one JSON object per line.\n  Preferred for programmatic consumers — types are\n  preserved (numbers stay numbers, `null` stays `null`) and rows can\n  be parsed incrementally.\n- `Accept: text/csv` → CSV download. The header row is the qualified\n  field names (e.g. `rules.ruleName`). List-typed fields\n  (`jobs.daysOfWeek`, `monitors.dimensionNames`, `rules.dimensionNames`)\n  render as pipe-delimited cells (`Completeness|Accuracy`) so\n  consumers don't have to handle quoted-comma CSV.\n\nWhen `Accept` is absent or `*/*`, the server returns\n`application/x-ndjson`; any other media type is rejected with\nHTTP 406. Both formats stream the same rows in the same order; only\nthe encoding differs.\n\n**Topics.** `JOBS`, `MONITORS`, and `RULES` are mutually\njoinable — any non-empty combination of them is valid. Quality\ndimensions are not a topic: the names of the quality dimensions\nassigned to a monitor (and to a rule — a rule is a `RULE`-type\nmonitor) are surfaced inline on the row as the\n`monitors.dimensionNames` / `rules.dimensionNames` list field\n(active assignments only; empty when none are assigned).\n\nTo discover what topics can be joined call GET `/egress/manifest` first. Each topic's\n`joinsTo` lists the other topics it can be joined to; your selected\n`topics` are valid if they form a connected subgraph over those edges.\nThe manifest also lists each field's `filterable` flag and\n`allowedOperators`, so a client can fully validate a request locally\nbefore POSTing.\n\n**Filters.** Optional predicates in the body's `filters` array, **ANDed**\ntogether (omit for no filtering beyond RBAC and the default window). Each\n`EgressFilter` is a `field`, an `op`, and a value whose shape depends on\nthe operator:\n- `value` (a single scalar) for `EQ`, `NE`, `LIKE`, `GT`, `GTE`, `LT`, `LTE`\n- `values` (an array) for `IN`, `NOT_IN`\n- neither for `IS_NULL`, `IS_NOT_NULL`\n\n`field` is the qualified name `<topic>.<apiName>` (e.g. `rules.ruleName`)\nand must belong to a **selected** topic; each field permits only a subset\nof operators. Call `GET /egress/manifest` to discover the filterable\nfields and their `allowedOperators`. A request fails with HTTP 400 if a\nfilter names an unknown field, uses an operator the field doesn't allow,\nor references a field whose topic isn't in `topics`. Filtering on any\n`*.updatedAt` field also overrides the default time window (see below).\n\n**Ordering.** Custom sort keys are not currently a request parameter.\nRows are always returned ordered by `<granularity>.updatedAt`\ndescending — the same field the default time window keys on (rules >\nmonitors > jobs) — followed by a unique tiebreaker for deterministic\nstreaming.\n\n**Projection.** is not currently a request parameter. Each row is a\nkey/value map containing all projectable fields of the selected\ntopics, in manifest order (fields marked `optIn: true` are excluded\nunless explicitly enabled — see catalog assets below). Use\n`GET /egress/manifest` to discover the supported topics, fields,\noperators, and opt-in flags.\n\n**Catalog assets (opt-in).** Set `includeCatalogAssets` (query parameter\nor request-body property — enrichment applies when either is `true`;\ndefault `false`) to add, to each row, the DGC Catalog assets it maps to.\nThree field groups are populated, all omitted when the flag is off:\n\n- **Table** — `jobs.tableCatalogAssetId` / `...DisplayName` / `...Type`:\n  the Catalog `Table` asset for the row's table. One per row.\n- **Column** — `monitors.columnCatalogAsset*` and\n  `rules.columnCatalogAsset*`: the `Column` asset for the row's column\n  (`monitors.columnName` / `rules.ruleColumnName`). One per row, or\n  `null` when the row has no column scope (e.g. a dataset-level monitor).\n- **Business Rule** — `monitors.businessRuleLinks`: the `Business Rule`\n  assets linked to the monitor, matched by identity (a rule surfaces here\n  as its `RULE`-type monitor). Collapsed into one list of\n  `\"<assetId>::<signifier>\"` entries, so a monitor linked to several rules\n  stays one row (no row multiplication).\n\nTwo query parameters trim the enrichment (both default `false`):\n`excludeColumnAssets` omits the Column group; `excludeRuleAssets` omits\nthe Business Rule group. Both are no-ops unless `includeCatalogAssets`\nis in effect.\n\n**Default time window.** When the request omits any `*.updatedAt`\nfilter, the server injects a rolling window on the `updatedAt` of a\nselected topic, anchored in the order monitors > rules > jobs.\nIts length is the `window` query parameter in days, defaulting to 90.\nTo set an exact range instead, filter explicitly on any `*.updatedAt`\nfield — the server suppresses the injected window (and ignores `window`)\nonce any such filter is present. The default-window contract is also\nsurfaced in `defaultWindow` on the manifest response.\n\n**Permissions**\n- **Required:** `DATA_QUALITY` and `DATA_QUALITY_JOB_VIEW`. Results are\n  scoped to the jobs the caller can see.\n- **Global bypass:**\n  - `DATA_QUALITY` and `VIEW_PERMISSIONS_VIEW_ALL`\n  - `DATA_QUALITY` and `RESOURCE_MANAGE_ALL`","operationId":"exportEgressData","parameters":[{"name":"window","in":"query","required":false,"description":"Rolling look-back window, in days, for the auto-injected time\nfilter. The server bounds a selected topic's `updatedAt` to\n`>= now - window` days, anchoring on the topic in the order\nmonitors > rules > jobs (`monitors.updatedAt` whenever monitors are\nselected, else `rules.updatedAt`, else `jobs.updatedAt`). Defaults\nto 90, capped at 365. Ignored when the request body already carries\nan explicit `*.updatedAt` filter — that filter wins.","schema":{"type":"integer","format":"int32","minimum":1,"maximum":365,"default":90}},{"name":"includeCatalogAssets","in":"query","required":false,"description":"Opt in to catalog-asset enrichment — the query-parameter equivalent\nof the request body's `includeCatalogAssets`, usable on a body-less\nrequest. Enrichment is applied when this **or** the body flag is\n`true`. Default `false`. See **Catalog assets** in the operation\ndescription for the fields populated, the row-multiplication caveat,\nand the cost.","schema":{"type":"boolean","default":false}},{"name":"excludeRuleAssets","in":"query","required":false,"description":"When catalog-asset enrichment is in effect (`includeCatalogAssets`\n`true`), skip the `monitors` `Business Rule` asset enrichment\n(`monitors.businessRuleLinks`). Default `false` (business-rule links\nincluded). Use this to avoid the linked-rule asset lookup when only\ntable and/or column assets are needed. No effect when\n`includeCatalogAssets` is not in effect.","schema":{"type":"boolean","default":false}},{"name":"excludeColumnAssets","in":"query","required":false,"description":"When catalog-asset enrichment is in effect (`includeCatalogAssets`\n`true`), skip the DGC `Column` asset enrichment of the `monitors`\nand `rules` topics (`monitors.columnCatalogAsset*`,\n`rules.columnCatalogAsset*`). Default `false` (column assets\nincluded). No effect when `includeCatalogAssets` is not in effect.","schema":{"type":"boolean","default":false}},{"name":"completionMarker","in":"query","required":false,"description":"Append a trailing completion marker so a consumer can distinguish a\ncomplete extract from one truncated by a mid-stream failure (or a\nproxy stream timeout). NDJSON ends with a final\n`{\"_complete\":true,\"rowCount\":N}` line; CSV ends with a\n`# complete rowCount=N` comment line. Default `true`. Set `false`\nfor a byte-clean body (e.g. naive CSV readers that don't skip\n`#`-prefixed comment lines), at the cost of losing truncation\ndetection.","schema":{"type":"boolean","default":true}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressRequest"}}}},"responses":{"200":{"description":"The egress export, streamed in the format selected by the\n`Accept` header (`application/x-ndjson` by default, or `text/csv`).\nThe response carries `Content-Disposition: attachment` so browsers\ndownload to disk; the filename extension reflects the negotiated\nformat (`.jsonl` / `.csv`).\n\n**Streaming semantics.** Both response schemas are declared with\n`format: binary` even though the bodies are text — this hints to\nSDK codegen to produce a streaming `Resource` / `InputStream`\nreturn type instead of buffering the entire payload in memory as\na `String`. Without that hint, regenerated SDKs default to\nstring-buffered responses, which defeats the streaming-export\ndesign (and would OOM on large result sets). Treat the body as\ntext at the wire level; treat the SDK return type as a stream.\n\n**Stream completeness.** Because the body streams, a failure after\nthe first byte cannot change the HTTP status — it surfaces only as a\nshort stream (plus a server-side error log) and can look like a\nsuccessful, fully-read extract. To let consumers detect this, the\nstream always ends with an explicit completion marker once every row\nhas been written:\n- NDJSON: a final line `{\"_complete\":true,\"rowCount\":N}` (data rows\n  never carry a `_complete` key).\n- CSV: a trailing comment line `# complete rowCount=N`.\n\nA consumer that reaches end-of-stream **without** seeing the marker\nmust treat the extract as truncated/failed, not complete. `rowCount`\nis the number of data rows emitted (excludes the header and marker).","headers":{"Content-Disposition":{"description":"Attachment with filename hint, e.g. `attachment; filename=\"egress-export-2026-04-28.jsonl\"` (`.csv` for the CSV format).","required":true,"schema":{"type":"string"}}},"content":{"application/x-ndjson":{"schema":{"type":"string","format":"binary","description":"Newline-delimited JSON ([JSON Lines](https://jsonlines.org)):\none JSON object per line, in stream order. Each object is\nkeyed by the qualified field names of the selected topics\n(see the `ruleResultsStream` example below and\n`GET /egress/manifest` for the full field set). The body\nstreams as text at the wire level — parse it line by line,\nnot as a single JSON document. The final line is a completion\nmarker `{\"_complete\":true,\"rowCount\":N}` (see **Stream\ncompleteness** on the 200 response) — distinguish it from data\nrows by the reserved `_complete` key."}},"text/csv":{"schema":{"type":"string","format":"binary","description":"CSV (UTF-8). The header row is the qualified field names;\none data row per result row, in stream order. The stream ends\nwith a trailing comment line `# complete rowCount=N` (see\n**Stream completeness** on the 200 response)."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"406":{"$ref":"#/components/responses/NotAcceptable"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Discover data-egress topics, fields, and join graph

> Returns the canonical metadata describing which topics can be combined,\
> which fields each topic exposes, and which operators are valid per\
> field. Use this endpoint to drive client-side validation.\
> \
> \`joinsTo\` (per topic) is the authoritative join graph: the list of\
> topics each one can be joined to. Use it to determine which \`topics\`\
> combinations are valid for\
> \`POST /egress/export\` (a selection must form a connected subgraph)\
> and to drive client-side validation of fields and operators.\
> \
> \*\*Permissions\*\*\
> \- \*\*Required:\*\* \`DATA\_QUALITY\`. (No resource scoping — this is\
> &#x20; metadata about the API itself.)

```json
{"openapi":"3.0.3","info":{"title":"Data Quality Collibra API","version":"1.3.0"},"tags":[{"name":"Data Egress","description":"Bulk extraction of DQ data — jobs, monitors, and rules joined across topics and streamed (NDJSON or CSV) in a single pass for BI tools, data pipelines, and integrations."}],"servers":[{"description":"Data Quality API","url":"/rest/dq/1.0"}],"security":[{"basicAuth":[]},{"jwtAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"description":"Collibra REST API authentication using Basic Authentication.","type":"http","scheme":"basic"},"jwtAuth":{"description":"Collibra REST API authentication using JSON Web Token.","type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EgressManifest":{"type":"object","required":["topics"],"properties":{"topics":{"type":"array","items":{"$ref":"#/components/schemas/EgressManifestTopic"}},"defaultWindow":{"$ref":"#/components/schemas/EgressManifestDefaultWindow"}}},"EgressManifestTopic":{"type":"object","required":["name","fields"],"properties":{"name":{"type":"string","description":"Topic identifier in UPPER_SNAKE_CASE. Mirrors the request-side\n`EgressTopic` enum (currently `JOBS`, `MONITORS`, `RULES`) but the\nresponse is free-form string so new topics can be added without\nbreaking SDK switch-on-known-values code.\nNote: qualified field names (e.g. `rules.ruleName`) use the\nlowercase form — that grammar is intentionally distinct from this\nenum."},"joinsTo":{"type":"array","uniqueItems":true,"description":"The topics this one can be joined to (UPPER_SNAKE_CASE, matching\n`name`). Reachability is symmetric — if A lists B, then B lists A.\nUse it to validate that a `topics` selection forms a connected\nsubgraph. Join-key columns are not exposed; clients need only\nreachability.","items":{"type":"string"}},"fields":{"type":"array","items":{"$ref":"#/components/schemas/EgressManifestField"}}}},"EgressManifestField":{"type":"object","required":["apiName","type","filterable","projectable","allowedOperators"],"properties":{"apiName":{"type":"string","description":"Field name within its topic. Combined with the topic as `<topic>.<apiName>`."},"type":{"type":"string","description":"Logical type of the field for filter-value coercion. Free-form\nstring (not an enum) so the server can introduce new types\nwithout breaking SDK switch-on-known-values code. Currently one\nof: `STRING`, `INTEGER`, `LONG`, `DOUBLE`, `BOOLEAN`,\n`TIMESTAMP`, `UUID`, `STRING_LIST`. Clients should treat unknown\nvalues as opaque and fall back to string handling."},"filterable":{"type":"boolean","description":"When `true`, this field can appear in `EgressFilter.field`. When\n`false`, the server rejects any filter referencing it with HTTP 400."},"projectable":{"type":"boolean","description":"When `true`, this field is included in the response projection\n(unless `optIn: true`). When `false`, the field is never returned —\nit exists only as a filter target."},"allowedOperators":{"type":"array","uniqueItems":true,"description":"Operators the server accepts when filtering this field. Items\nmirror the request-side `EgressOperator` enum (currently\n`EQ`, `NE`, `IN`, `NOT_IN`, `LIKE`, `GTE`, `LTE`, `GT`, `LT`,\n`IS_NULL`, `IS_NOT_NULL`) but the response shape is free-form\nstring so new operators can be added without breaking SDK\nswitch-on-known-values code.","items":{"type":"string"}},"optIn":{"type":"boolean","default":false,"description":"When `true`, the field is excluded from the default response\nprojection. The catalog-asset fields are opt-in and become\nprojectable when the request sets `includeCatalogAssets`. Projection\nis not otherwise a request parameter, so any other opt-in field\n(e.g. `rules.ruleColumnName`) is reachable only as a filter target."}}},"EgressManifestDefaultWindow":{"type":"object","description":"Describes the implicit time-window filter the server injects when the\ncaller does not supply one. Clients that want a different window range\nmust filter explicitly on any `*.updatedAt` field — the server detects\nthe explicit filter and suppresses the default.","required":["durationDays","anchorField","appliesWhen"],"properties":{"durationDays":{"type":"integer","description":"Default number of days back from `now` (UTC) used as the lower\nbound. Overridable per request via the `window` query parameter on\n`POST /egress/export`."},"anchorField":{"type":"string","description":"Suffix the server appends to the anchor topic to compute the\nwindow field. The anchor topic is chosen in the order\nmonitors > rules > jobs — e.g. `updatedAt` resolves to\n`monitors.updatedAt` whenever monitors are selected, otherwise\n`rules.updatedAt`, otherwise `jobs.updatedAt`."},"appliesWhen":{"type":"string","description":"Plain-text rule describing when the window is injected."}}},"StandardErrorResponse":{"type":"object","description":"Error response returned by the Data Quality API.","required":["statusCode","errorCode","titleMessage","userMessage"],"properties":{"statusCode":{"type":"integer","description":"HTTP status code corresponding to the error."},"errorCode":{"type":"string","description":"Internal error code representing the specific error type."},"titleMessage":{"type":"string","description":"A brief title summarizing the error."},"userMessage":{"type":"string","description":"Detailed, user-friendly message explaining the error and possible remediation steps."}}}},"responses":{"Unauthorized":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardErrorResponse"}}}}}},"paths":{"/egress/manifest":{"get":{"tags":["Data Egress"],"summary":"Discover data-egress topics, fields, and join graph","description":"Returns the canonical metadata describing which topics can be combined,\nwhich fields each topic exposes, and which operators are valid per\nfield. Use this endpoint to drive client-side validation.\n\n`joinsTo` (per topic) is the authoritative join graph: the list of\ntopics each one can be joined to. Use it to determine which `topics`\ncombinations are valid for\n`POST /egress/export` (a selection must form a connected subgraph)\nand to drive client-side validation of fields and operators.\n\n**Permissions**\n- **Required:** `DATA_QUALITY`. (No resource scoping — this is\n  metadata about the API itself.)","operationId":"getEgressManifest","responses":{"200":{"description":"Data egress manifest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressManifest"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```
