> 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; \`monitors.affectedColumnChanges\`)\
> &#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.\
> \
> \*\*Schema-change affected columns.\*\* \`monitors.affectedColumnChanges\`\
> lists the columns a schema change affected, as \`"\<CHANGE\_TYPE>::\<column>"\`\
> elements. Populated only on the schema-change monitor\
> (\`monitors.monitorType = SCHEMA\_CHANGE\`); empty on every other row.\
> \
> \| \`CHANGE\_TYPE\` | meaning |\
> \|---|---|\
> \| \`COLUMN\_ADDED\` | the column appeared in this run's schema |\
> \| \`COLUMN\_REMOVED\` | the column disappeared from this run's schema |\
> \| \`COLUMN\_DATA\_TYPE\_CHANGED\` | the column's data type changed |\
> \| \`COLUMN\_SPECIAL\_CHARACTERS\` | the name contains characters invalid in an\
> &#x20; identifier (pullup jobs only — pushdown reports such a column as an\
> &#x20; ordinary add/remove/type change) |\
> \
> Split each element on the \*\*first\*\* \`::\`: the vocabulary above is closed\
> and colon-free, so the remainder is the column name even when the name\
> itself contains \`::\`. Treat an unknown \`CHANGE\_TYPE\` as a\
> forward-compatible addition, not an error.\
> \
> Two quirks of the column name: a \`|\` is replaced with \`U+FFFD\`\
> (\`\&#65533;\`) because the pipe is the reserved list delimiter, and for\
> \`COLUMN\_SPECIAL\_CHARACTERS\` the element carries the bare name while\
> \`monitors.columnName\` keeps the engine's \`\[ name ]\` wrapper.\
> \
> An empty list on a schema-change row means \*\*no detail was available\*\* —\
> no change detected, or the detail rows were masked or unparseable — not\
> that nothing changed.\
> \
> \*\*Prefer this field over \`monitors.columnName\`\*\* for affected columns:\
> there, a wide change degrades to the literal \`ALL\`, which is also what a\
> clean run stores. \`columnName\` is unchanged and still returned.\
> \
> Not filterable (\`allowedOperators: \[]\`): the value is computed per row, so\
> a \`filters\` entry naming it is rejected with HTTP 400 — filter on\
> \`monitors.monitorType\` and post-process instead.\
> \
> \*\*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 \`GLOBAL\_MANAGE\_ALL\_RESOURCES\`

```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  `monitors.affectedColumnChanges`)\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**Schema-change affected columns.** `monitors.affectedColumnChanges`\nlists the columns a schema change affected, as `\"<CHANGE_TYPE>::<column>\"`\nelements. Populated only on the schema-change monitor\n(`monitors.monitorType = SCHEMA_CHANGE`); empty on every other row.\n\n| `CHANGE_TYPE` | meaning |\n|---|---|\n| `COLUMN_ADDED` | the column appeared in this run's schema |\n| `COLUMN_REMOVED` | the column disappeared from this run's schema |\n| `COLUMN_DATA_TYPE_CHANGED` | the column's data type changed |\n| `COLUMN_SPECIAL_CHARACTERS` | the name contains characters invalid in an\n  identifier (pullup jobs only — pushdown reports such a column as an\n  ordinary add/remove/type change) |\n\nSplit each element on the **first** `::`: the vocabulary above is closed\nand colon-free, so the remainder is the column name even when the name\nitself contains `::`. Treat an unknown `CHANGE_TYPE` as a\nforward-compatible addition, not an error.\n\nTwo quirks of the column name: a `|` is replaced with `U+FFFD`\n(`&#65533;`) because the pipe is the reserved list delimiter, and for\n`COLUMN_SPECIAL_CHARACTERS` the element carries the bare name while\n`monitors.columnName` keeps the engine's `[ name ]` wrapper.\n\nAn empty list on a schema-change row means **no detail was available** —\nno change detected, or the detail rows were masked or unparseable — not\nthat nothing changed.\n\n**Prefer this field over `monitors.columnName`** for affected columns:\nthere, a wide change degrades to the literal `ALL`, which is also what a\nclean run stores. `columnName` is unchanged and still returned.\n\nNot filterable (`allowedOperators: []`): the value is computed per row, so\na `filters` entry naming it is rejected with HTTP 400 — filter on\n`monitors.monitorType` and post-process instead.\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 `GLOBAL_MANAGE_ALL_RESOURCES`","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"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developer.collibra.com/api/references/data-quality/data-egress.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
