Skip to content

API

1 Purpose

The DataForge backend exposes a public API for external integrations and AI agents.

The public API has two versions, each under its own base path:

Endpoint group Base path Contents Audience
Public DF API v1 /df-api/v1 Read-only: projects, versions, RMD content (measures, dimensions, facts), data marts, connections, dimension groups, fact tables, relationships, combined RMD export External integrations, AI agents
Public DF API v2 /df-api/v2 Read and write: full CRUD over projects, versions, RMD content, dimension groups, fact tables, and relationships; read-only data marts and connections; version export/import and Git connection management; idempotent writes and SQL generation for measures External integrations, CI/CD, AI agents

Core principles that apply to every public API call:

Principle Description
Versioned URL The public API is versioned via the URL path (/v1/). Within a major version the contract is additive only — new optional fields may be added, but existing fields are not removed or renamed
Versioned data Every endpoint that operates on RMD content, fact tables, data marts, or connections is scoped to a project version
Data access v1 (/df-api/v1) is read-only. df-api/v2 adds full read/write CRUD over projects, versions, RMD content, and the data model (the Public API v2 page). No public API endpoint ever runs data queries against connected databases or exposes database credentials
Throttled Both versions share one limit: 100 requests per 60 seconds per API key (section 2.4)
License-gated The entire public API is gated on the calling company holding a valid license
Audited Every public API request — its authentication and its outcome, successful or failed — is recorded in the audit log

Full base URLs on a deployed system: https://<host>/df-api/v1 and https://<host>/df-api/v2. On-premises installations use the host configured in the deployment template; nginx terminates TLS in front of the backend.

2 Authentication and Authorization

2.1 API Key

The public API uses long-lived API keys created in the user card (see the API keys page). Each user owns at most one active API key; generating a new one replaces the previous one. The plaintext key is shown to the operator at generation time and not stored — only its bcrypt hash is persisted.

ApiKeyGuard (applied to every v1 and v2 endpoint) performs the following checks in order on every request:

  1. API key presence. If the X-Api-Key header is missing → 401 API_KEY.KEY_MISSING.
  2. API key validity. The supplied key is bcrypt-compared against every stored hash; on mismatch → 401 API_KEY.INVALID_KEY.
  3. User status. If the matched user is not ENABLED → 403 API_KEY.ACCOUNT_LOCKED.
  4. IP filtering. The client IP, resolved from the source trusted for the deployment mode, is checked against the company's IP whitelist and blacklist. Blocked → 403 API_KEY.IP_BLOCKED.
  5. Company present. If the user has no company → 403 API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE.
  6. License valid. The company license is checked. Failure → 403 API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE. See section 9.5.
  7. Audit log. A success or failure record is written to the audit log (type API_ACCESS, action API_ACCESS_SUCCESSFUL / API_ACCESS_FAILED).

2.2 Roles and project access

Most public API endpoints are read-only and apply no role check of their own. The df-api/v2 write endpoints enforce per-project write access (see below and section 1 of the Public API v2 write operations page). The user's status still matters for authentication: the key owner must be ENABLED.

Per-project access inheritance. An API key inherits the interactive (UI) project access of the key owner. As a result:

  • Endpoints scoped to a single project (/projects/{id}/versions, all version-scoped endpoints, and the data-model / data-mart endpoints) return 404 Not Found when the key owner has no access to that project — existence is not disclosed to callers without access.
  • Project-list endpoints (GET /projects on v1 and v2) are filtered to the projects the key owner can access; inaccessible projects are omitted from the page and from the total count.

This applies uniformly to v1 and v2.

df-api/v2 is a full read/write CRUD API (the Public API v2 page). RMD and data-model writes require the key owner to resolve to an effective project role of developer or higher; the access-management endpoints (section 3 of the Public API v2 write operations page) are additionally restricted to the project owner or a user with the Administrator or Super administrator role. Version export and the import dry runs require analyst or higher, a version import requires developer or higher, and Git connection management requires COMPANY_ADMIN (sections 4–5 of the Public API v2 write operations page). v1 remains read-only.

2.3 IP Filtering

IP filtering is applied on every public API call, right after the key is validated.

A company may enable IP whitelisting, IP blacklisting, or both. Each list supports either exact IPv4 addresses or CIDR ranges. When whitelisting is enabled, requests from IPs not on the list are rejected; when blacklisting is enabled, requests from IPs on the list are rejected. Failed IP checks on the public API are written to the audit log as API_ACCESS / API_ACCESS_FAILED.

2.4 Throttling

Both public API versions — /df-api/v1 and /df-api/v2 — apply the same per-API-key throttling: no more than 100 requests per 60 seconds per key (a sliding window, counted per X-Api-Key value). Every public API response carries the headers:

Header Description
X-RateLimit-Limit Maximum requests allowed in the window
X-RateLimit-Remaining Requests remaining in the current window
X-RateLimit-Reset Unix timestamp when the counter resets

When the limit is exceeded the API returns 429 Too Many Requests with the key DF_API.RATE_LIMIT_EXCEEDED in originalMessage; on df-api/v2 the response additionally carries code: "rate_limit_exceeded" (section 4 of the Public API v2 page). The rejected request is audited as API_ACCESS_FAILED (section 7).

Counters are kept in a store shared by every backend instance (Redis), so the limit applies to the key as a whole rather than per instance: a parallel burst spread across several instances is throttled exactly like a sequential one. If the shared store is unavailable, counting temporarily falls back to the instance — API availability is unaffected, only the accuracy of the limit degrades.

2.5 License Gating

The license is checked after authentication and IP filtering. Every public API endpoint is rejected when the company has no valid license. The error returned is the same regardless of the underlying license problem: 403 Forbidden with code API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE. See section 5 for the conditions and recovery procedure.

2.6 Transport Security

All public API endpoints must be served over HTTPS with TLS 1.2 or higher. The on-premises deployment template provisions nginx with TLS termination in front of the backend; the backend itself listens on plain HTTP within the trusted network.

API keys are stored as bcrypt hashes and are never returned in responses. See section 6 for the full list of fields that are never returned.

3 Common Request and Response Conventions

3.1 Request format

Property Value
Content-Type application/json for JSON bodies
Charset UTF-8
Auth header X-Api-Key: <key>
Language Optional Accept-Language header; language query parameter takes precedence

3.2 Pagination

List endpoints use a unified pagination shape. Query parameters:

Parameter Type Default Description
page integer 1 1-indexed page number
pageSize integer 20 Maximum 100. The data mart, connection and Git connection lists (v1 and v2) and the v1 dimension group, fact table and relationship lists refuse a larger value with 400 DF_API.PAGE_SIZE_EXCEEDED; the v2 project, version, RMD content, dimension group, fact table and relationship lists silently clamp it to 100; the v1 project, version and RMD content endpoints do not cap it
Filter params varies — Specific filters per endpoint (documented inline)

Response envelope (most DF API list endpoints):

{
  "data_marts": [ /* items */ ],
  "pagination": { "page": 1, "pageSize": 20, "total": 45, "total_pages": 3 }
}

Response envelope (RMD content list endpoints — …/measures, …/dimensions, …/facts on df-api/v1, the projects and versions lists, and every df-api/v2 list endpoint):

{
  "measures": [ /* items */ ],
  "pagination": { "total": 42, "page": 1, "pageSize": 20, "totalPages": 3 }
}

3.3 Localization

Public API responses honour the language query parameter (ru or en). Only descriptive text values (status labels, type labels, dropdown values) are localized; JSON keys are always English.

3.4 Timestamps

All timestamps in responses are ISO 8601 (YYYY-MM-DDTHH:MM:SSZ).

3.5 Output formats

The RMD content endpoints (…/measures, …/dimensions, …/facts), the project and version listings, and the data-model and RMD-export endpoints support ?format=json (default) and ?format=xlsx. When xlsx is requested, the response body is { "downloadUrl": "<signed S3 URL valid for 15 minutes>" }. The data-marts and connections endpoints return JSON only. An invalid format value returns 400 Bad Request with code DF_API.INVALID_FORMAT.

3.6 Source object

Every field that points at a physical location inside a connected database uses one and the same object:

{
  "connection": "Production PostgreSQL",
  "db": "analytics_db",
  "schema": "public",
  "table": "fact_sales",
  "column": "amount"
}
Field Type Required Description
connection string yes Name of the connection the source belongs to
db string yes Database of that connection
schema string | null no Database schema
table string yes Table name
column string | null no Column name; null when the reference is to a whole table

How absence is spelled. Read responses use two different empty values, and both are accepted on write:

Object No schema is No column is
source objects (connected_source, primary_key, foreign_key) "" — the value the RMD export and import share null
connection and table descriptions (GET /connections, tables[].schema) null —

On write, schema and column each accept the empty string, null, and the field being absent: all three mean "not supplied", so an object read from any endpoint can be sent straight back. Only db and table are required.

The word schema in four roles. Three of them are a schema name, the fourth is the key of a container object:

Where Type Meaning
GET /connections → schema string | null The schema chosen for the connection. PostgreSQL only; null for MS SQL and ClickHouse
GET /connections/{id}/schema → schema object Container: { connection, tables[] }. Called db_schema in the connection details response
…tables[].schema string | null The schema the table lives in. null for ClickHouse, which has no schemas
source object schema string Where the source lies. "" for MS SQL (folded into table) and ClickHouse

The shape is shared by connected_source (dimensions, facts), primary_key (dimension groups, fact-table details, relationships) and foreign_key (fact-table details, relationships). It is also the shape the product's own RMD export and import use, so an object read from the API can be fed straight into an RMD import file.

schema is dialect-specific:

  • PostgreSQL — the schema belongs to the connection, so the field repeats the connection's own schema;
  • MS SQL Server — the schema is folded into table (dbo.orders) and schema is empty;
  • ClickHouse — schemas do not exist; schema is empty.

connection is the only field that identifies a source unambiguously. One project version may hold several connections to the same database that differ by schema, credentials, or host — db cannot tell them apart, the connection name can (connection names are unique within a version).

Availability. connection is returned by v2 endpoints only (the Public API v2 page) and accepted by v2 write endpoints. v1 responses (sections 1–2 of the Public API v1 page) carry the same object without it.

The dialect rules above hold for every v2 endpoint. In v1 they are applied by the RMD endpoints (/rmd/*) only; the dimension-group, fact-table and relationship endpoints of v1 answer the schema stored on the row, falling back to the connection's own.

3.7 How endpoints are described

Every endpoint on the Public API v1, Public API v2 and Public API v2 write operations pages is documented with the same four blocks, in the same order:

Block Contents
Request The method and full path, followed by one table of every input the endpoint accepts: path parameters, query parameters, headers and body fields. Columns: Parameter (name; body fields use a dotted path such as options.include_rmd), In (path, query, header, body), Type, Required (yes / no), Description (default values, allowed values, constraints)
Details Behaviour that a client has to know and that does not fit the tables: access rules, side effects, idempotency, dialect specifics. Omitted when there is nothing to add
Response The success status, a representative JSON body and a field table (Field, Type, Description). Field paths are dotted; [] marks an array element (measures[].id)
Errors Codes this endpoint raises beyond the common ones. The codes every endpoint shares (authentication, license, rate limit, project and version resolution) are listed once in section 4 and are referred to as "common errors"

Two inputs are not repeated in the tables: the X-Api-Key header, which every endpoint requires (section 2.1), and the optional Accept-Language header, which every endpoint honours as the fallback for the language parameter (section 3.3). The Idempotency-Key header is listed only for the endpoints that honour it. Identifiers in paths are positive integers (section 4); in v2 bodies and responses they travel as strings.

4 Error Handling

Errors from v1 are returned in a single consistent four-field JSON shape:

{
  "message": "string",
  "originalMessage": "string",
  "statusCode": 404,
  "error": "string"
}
Field Description
message Localized, human-readable message (honours ?language / Accept-Language)
originalMessage The raw error key (e.g. DF_API.PROJECT_NOT_FOUND); stable identifier for clients
statusCode HTTP status code
error Exception class name

df-api/v2 uses its own filter and extends this envelope with two machine-readable fields — code and details. The shape is described in section 4 of the Public API v2 page and is identical across every v2 endpoint, including errors raised by the guards (invalid key, IP, license, rate limit).

Standard HTTP codes:

Code Meaning
200 Success
201 Created — v2 creating POSTs, and generate-sql on v1 (section 2.4 of the Public API v1 page)
204 No Content — v2 DELETEs
207 Multi-Status — a v2 bulk operation (…/bulk) was applied partially (section 1 of the Public API v2 write operations page)
400 Bad Request — validation, parameter, or business-rule violation
401 Unauthorized — missing or invalid API key
403 Forbidden — IP blocked, account locked, license invalid
404 Not Found — resource does not exist or is not visible to the caller
409 Conflict — duplicate name, referenced element, or in-flight idempotency key (v2 writes)
422 Unprocessable Entity — semantic write validation failed (formula/reference/dependency, global-version conflict) (v2 writes)
429 Too Many Requests — per-key rate limit exceeded (all groups)
500 Internal Server Error

Resource identifiers. Identifiers in the path (project_id, version_id, data_mart_id, connection_id, and so on) and the identifiers carried in v2 write bodies are positive integers up to 2147483647 (int4). A numeric value outside that range can match no row and is answered with 404 and the not-found code of the addressed resource (DF_API.PROJECT_NOT_FOUND, DF_API.VERSION_NOT_FOUND, DF_API.DATA_MART_NOT_FOUND, etc.) — exactly like a resource that does not exist. The rule applies uniformly to v1 and v2.

Errors common to every endpoint. The following codes can be returned by any public API endpoint; the per-endpoint "Errors" blocks on the endpoint pages do not repeat them.

HTTP df-api/v1 df-api/v2 (originalMessage / code) Condition
401 API_KEY.KEY_MISSING DF_API.INVALID_API_KEY / invalid_api_key X-Api-Key header missing
401 API_KEY.INVALID_KEY DF_API.INVALID_API_KEY / invalid_api_key The key matched no stored key
403 API_KEY.ACCOUNT_LOCKED DF_API.ACCOUNT_LOCKED / account_locked The key owner is not ENABLED
403 API_KEY.IP_BLOCKED DF_API.IP_NOT_ALLOWED / ip_not_allowed Client IP is blacklisted or outside the whitelist
403 API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE DF_API.LICENSE_INVALID / license_invalid The company has no valid license (section 5)
429 DF_API.RATE_LIMIT_EXCEEDED DF_API.RATE_LIMIT_EXCEEDED / rate_limit_exceeded The per-key quota of 100 requests / 60 s is exhausted (section 2.4)
400 DF_API.INVALID_PARAMETER DF_API.INVALID_PARAMETER / invalid_parameter A path identifier is not a number (df-api only)
404 DF_API.PROJECT_NOT_FOUND DF_API.PROJECT_NOT_FOUND / project_not_found The project does not exist or the key owner has no access to it
404 DF_API.VERSION_NOT_FOUND DF_API.VERSION_NOT_FOUND / version_not_found The version does not exist in the project
400 DF_API.INVALID_FORMAT DF_API.INVALID_FORMAT / invalid_format format is outside the values the endpoint accepts (section 3.5)
500 — DF_API.INTERNAL_ERROR / internal_error Unexpected server-side failure; no internal detail is returned

The complete code catalogue is in section 9.11.

5 License Validation

The license check is the single point of enforcement that decides whether a company's public API access is permitted. It runs after authentication and IP filtering.

The check answers 403 Forbidden when any of the following holds for the caller's company:

Condition Description
The company has no license record license is null
The license type is NO_LICENSE A placeholder license assigned by default before activation
The license status is INVALID Expired, never validated, or revoked
The license status is SUSPENDED License limits (users, projects, versions) exceeded

The public API maps all of these conditions to a single error so that license-state details are not leaked:

HTTP Code Body
403 API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE { "message": "API is not available without a valid license", "originalMessage": "API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE", "statusCode": 403, "error": "ForbiddenException" }

A failed access attempt caused by license invalidity is recorded in the audit log (type API_ACCESS, action API_ACCESS_FAILED).

To restore API access, a user with the Administrator role (or, in cloud installations, the Super administrator role) must upload a valid license through the License management screen and ensure the company is within the user/project/version limits of the licence tier.

6 Security Constraints

The following fields must never appear in any public API response:

Field Reason
password Database authentication credential (DB connections) and user authentication credential (login)
ssl_certificate, caCertificateFileName, clientCertificateFileName Certificate material
ssl_key, clientPrivateKeyFileName Private key material
token, apiKey, key JWT, refresh tokens, API keys, session tokens
connection_string May embed credentials
signature (license entity) License HMAC; never returned to clients
Any custom credential field User-defined sensitive values

Identifiers that are deliberately exposed because they are non-sensitive context:

Field Reason allowed
username (DB connection) Database user name — required for SQL building, no credential value
host, port, database, schema Network coordinates already known to anyone with read access to the data model

Encryption at rest:

Field Storage Cipher
API key database bcrypt
Remote DB password database AES (application-managed key)
Remote DB SSL files object storage (MinIO/S3) server-side encryption
License signature database HMAC; verified, never returned

7 Audit Logging

Every public-API request (v1 and v2) is recorded after the handler runs, so the outcome is known. Each entry carries type, action, actor, source IP, target object, and a free-form what field:

Event Type Action Trigger
Successful API request API_ACCESS API_ACCESS_SUCCESSFUL Request authenticates and its handler completes successfully
Failed API request API_ACCESS API_ACCESS_FAILED Authentication is denied (missing/invalid key, account locked, IP blocked, license invalid), or an authenticated request returns an error — a failed read, a failed df-api/v2 write, or a 429 rate-limit rejection

In addition, every successful df-api/v2 write (create/update/delete over RMD content, the data model, project access and Git connections, and a version import) is audited with a before/after snapshot of the affected entity: replacing a version by import records the overwritten version's label and content counts as the before. Version-transfer operations through the public API are not duplicated into the export/import journal visible in the UI — their only trace is the API_ACCESS records.

Audit-log fields:

Field Value
type Event category (e.g. API_ACCESS)
action Specific action within the category
who Email of the actor (API-key owner for public API)
from_where Client IP from the trusted source, or UNKNOWN
where Company name
what API version (DfApi v1 or DfApi v2; a 429 rejection is always recorded as DfApi v2 — the throttler shared by both versions knows only that name); for a failed request the denial or error reason is appended (e.g. … — Invalid API key), and for a df-api/v2 write a change summary is appended
before, after Entity snapshots for df-api/v2 write events; unused for read-only calls

Audit log retention is governed by company settings; entries are visible in the Audit Log screen for users with the Administrator or Super administrator role.

8 Error Codes Reference

The table consolidates error codes returned by the public API.

Code HTTP Description
API_KEY.KEY_MISSING 401 X-Api-Key header missing
API_KEY.INVALID_KEY 401 API key did not match any stored key
API_KEY.INVALID_ENCRYPTED_API_KEY 400 Encrypted API key payload could not be decoded
API_KEY.AUTH_FAILED 401 Generic authentication failure
API_KEY.ACCOUNT_LOCKED 403 User is not in ENABLED status
API_KEY.IP_BLOCKED 403 Client IP on blacklist or outside whitelist
API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE 403 Company has no valid license
DF_API.INVALID_PARAMETER 400 Path or query parameter validation failed; in v2 access management — an invalid or missing accessLevel, an attempt to elevate above the global role, an ineligible new owner
DF_API.PAGE_SIZE_EXCEEDED 400 pageSize exceeds 100
DF_API.INVALID_TYPE 400 Invalid type filter for data marts
DF_API.INVALID_MERGE_TYPE 400 Invalid merge_type filter for data marts
DF_API.INVALID_DB_TYPE 400 Invalid db_type filter for connections
DF_API.INVALID_STATUS 400 Invalid status filter for connections
DF_API.INVALID_FORMAT 400 format is not json or xlsx (for v2 data marts and connections: not json)
DF_API.VALIDATION_FAILED 400 Body or query does not match the schema (v2); details[] lists the fields
DF_API.PROJECT_NOT_FOUND 404 Project does not exist or is not accessible
DF_API.VERSION_NOT_FOUND 404 Version does not exist or is not accessible
DF_API.DATA_MART_NOT_FOUND 404 Data mart does not exist in the version
DF_API.CONNECTION_NOT_FOUND 404 Connection does not exist in the version
DF_API.DIMENSION_GROUP_NOT_FOUND 404 Dimension group does not exist in the version
DF_API.FACT_TABLE_NOT_FOUND 404 Fact table does not exist in the version
DF_API.RELATIONSHIP_NOT_FOUND 404 Relationship does not exist in the version
DF_API.LICENSE_LIMIT_REACHED 403 A license limit (e.g. the number of versions) is reached — creating a version or importing into a new one is refused (v2)
DF_API.WRITE_ACCESS_DENIED 403 Key owner's effective project role is below the required one; caller is neither the project owner nor an administrator (v2 access management)
DF_API.INVALID_API_KEY 401 X-Api-Key missing, or the key matched nothing
DF_API.ACCOUNT_LOCKED 403 The key owner is deactivated
DF_API.IP_NOT_ALLOWED 403 Client IP is blacklisted or outside the whitelist
DF_API.LICENSE_INVALID 403 The company has no valid license
DF_API.MISSING_REQUIRED_FIELD 400 A required field is missing (e.g. on a PUT full replacement) (v2 write)
DF_API.INVALID_ENUM_VALUE 400 A select/enum field value is not among the allowed options (v2 write)
DF_API.ID_MISMATCH 400 Body id does not match the path id (v2 write)
DF_API.INVALID_RELATIONSHIP_TYPE 400 relationship_type must be many_to_one (v2 write)
DF_API.INVALID_SOURCE_CONNECTION 400 Source object names a connection that does not exist in the project version (v2 write)
DF_API.INVALID_SOURCE_DB 400 Source object's db is not the database name of the connection it names (v2 write)
DF_API.INVALID_SOURCE_SCHEMA 400 The specified schema does not exist in the connection (PostgreSQL only) (v2 write)
DF_API.INVALID_SOURCE_TABLE 400 Source object's table is not in the connection's cached schema (v2 write)
DF_API.INVALID_SOURCE_COLUMN 400 Source object's column is not in that table (v2 write)
DF_API.CONNECTION_MISMATCH 400 A relationship key names a different connection than the fact table or dimension group it belongs to (v2 write)
DF_API.INVALID_IDEMPOTENCY_KEY 400 Idempotency-Key is not a valid UUID v4 (v2 write)
DF_API.DUPLICATE_NAME 409 An element, project, or version with the same name already exists in scope (v2 write)
DF_API.DUPLICATE_RELATIONSHIP 409 A relationship already exists for this fact table → dimension group (v2 write)
DF_API.DUPLICATE_LEVEL 409 A requested hierarchy level is already held by another dimension of the group; the message names the level (v2 write)
DF_API.CONSTRAINT_VIOLATION 409 Element is still referenced and cannot be deleted or unassigned (v2 write)
DF_API.IDEMPOTENCY_IN_PROGRESS 409 A request with the same Idempotency-Key is still in flight (v2 write)
DF_API.INVALID_FORMULA_SYNTAX 422 Measure formula failed to parse (v2 write)
DF_API.FORMULA_REFERENCE_NOT_FOUND 422 Measure formula references a non-existent element (v2 write)
DF_API.CIRCULAR_DEPENDENCY 422 Measure formula introduces a circular reference (v2 write)
DF_API.GLOBAL_VERSION_CONFLICT 422 is_global cannot be set — it conflicts with another global version; deleting the current global version is refused with the same code (v2 write)
DF_API.INVALID_PARAMETER_TYPE 422 A dimension passed to a period function of the formula is bound to a source column that is not a date or time (v2 write)
DF_API.BULK_REJECTED 422 No row of a bulk operation was applied (v2 write); partial success answers 207 Multi-Status
DF_API.SQL_GENERATION_FAILED 422 SQL for a measure could not be generated with include_sql=true (v2)
DF_API.MEASURE_HEALTH_ERROR 422 A measure with the Error health status cannot be assigned to a fact table; reported per item in failed[] (v2 write)
DF_API.RESOURCE_NOT_FOUND 404 Target element or membership does not exist; the target user of access management does not exist or is outside the project's company (v2 write)
DF_API.GIT_CONNECTION_FAILED 422 The Git repository is unreachable or rejected the credentials (version transfer, Git connections)
DF_API.GIT_PUSH_FAILED 422 The push was rejected: the branch changed during the export or is protected (export to Git)
DF_API.UNPROCESSABLE_ENTITY 422 The import source is invalid or exceeds the size limits (version transfer)
SQL_GENERATION_FAILED 201/200 (in validation_errors of the generate-sql response) Data mart cannot currently produce SQL
DF_API.RATE_LIMIT_EXCEEDED 429 The per-key quota of 100 requests / 60 s is exhausted (v1 and v2; v2 adds code: rate_limit_exceeded)
DF_API.INTERNAL_ERROR 500 Unexpected server-side error (v2 answers code: internal_error with no internal detail)

On df-api/v2 the keys of the internal services (PROJECT.*, VERSION.*, DATAMART.*, DATAMART_DB.*, GIT_CONNECTION.*, VCS_EXPORT.*, VCS_IMPORT.*, LICENSE.*) are mapped onto the DF_API.* keys of this table before they leave the API; keys without an explicit mapping (including the access-management codes PROJECT.* and USER.NOT_FOUND) degrade to the generic code of their HTTP status: 400 → DF_API.INVALID_PARAMETER, 401 → DF_API.INVALID_API_KEY, 403 → DF_API.WRITE_ACCESS_DENIED, 404 → DF_API.RESOURCE_NOT_FOUND, 409 → DF_API.CONSTRAINT_VIOLATION, 422 → DF_API.UNPROCESSABLE_ENTITY, 429 → DF_API.RATE_LIMIT_EXCEEDED.