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:
- API key presence. If the
X-Api-Keyheader is missing →401API_KEY.KEY_MISSING. - API key validity. The supplied key is bcrypt-compared against every stored hash; on mismatch →
401API_KEY.INVALID_KEY. - User status. If the matched user is not
ENABLED→403API_KEY.ACCOUNT_LOCKED. - 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 →
403API_KEY.IP_BLOCKED. - Company present. If the user has no company →
403API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE. - License valid. The company license is checked. Failure →
403API.NOT_AVAILABLE_WITHOUT_VALID_LICENSE. See section 9.5. - Audit log. A success or failure record is written to the audit log (type
API_ACCESS, actionAPI_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) return404 Not Foundwhen the key owner has no access to that project — existence is not disclosed to callers without access. - Project-list endpoints (
GET /projectson 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) andschemais empty; - ClickHouse — schemas do not exist;
schemais 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.