diff --git a/content/manuals/enterprise/reports/_index.md b/content/manuals/enterprise/reports/_index.md new file mode 100644 index 00000000000..9660dccdfbc --- /dev/null +++ b/content/manuals/enterprise/reports/_index.md @@ -0,0 +1,238 @@ +--- +title: Usage reports +description: Learn how to retrieve enterprise usage reports for your Docker organization using the Reports API. +keywords: docker, enterprise, reports, usage, pulls, api, csv, organization access token, oat +weight: 20 +params: + sidebar: + group: Enterprise +--- + +Docker provides daily usage reports for organizations with a Docker Business +subscription. These reports contain pull activity data for your organization and +are available as CSV downloads through the Reports API. + +Reports are generated automatically. You use the API to list what is available +and download the files you need. + +## Prerequisites + +Before you begin, ensure you have: + +- A [Docker Business subscription](/subscription/details/) +- One of the following: + - Organization owner role + - A custom role that includes the **report-read** permission +- `curl` installed for making API requests +- `jq` installed for JSON parsing (optional, for formatting responses) + +## Authentication + +The Reports API requires an Organization Access Token (OAT). OATs are +org-scoped tokens designed for machine-to-machine access, making them +suitable for automated report retrieval workflows. Personal Access Tokens +(PATs) are not supported. + +1. [Create an organization access token](/enterprise/security/access-tokens/) + and select the **Report Read** scope under Organization permissions. + +2. Set your variables: + + ```bash + ORG="" + TOKEN="" + ``` + +3. Test the token: + + ```console + $ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \ + -H "Authorization: Bearer $TOKEN" | jq . + ``` + +You use this `TOKEN` value in the `Authorization: Bearer` header for all +subsequent API calls. + +## List available report types + +Discover which report types and cadences are available for your organization. + +```console +$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \ + -H "Authorization: Bearer $TOKEN" | jq . +``` + +Example response: + +```json +{ + "report_types": [ + { + "ReportType": "usage_pulls", + "Cadence": "daily" + } + ] +} +``` + +Each entry represents a distinct combination of report type and cadence. Use +these values in subsequent calls. + +## List reports + +List available reports for a given type and cadence. Reports are returned in +reverse chronological order (most recent first). + +```console +$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily" \ + -H "Authorization: Bearer $TOKEN" | jq . +``` + +Example response: + +```json +{ + "reports": [ + { + "ReportType": "usage_pulls", + "Cadence": "daily", + "Date": "2026-06-16", + "SizeBytes": 48210, + "Key": "my-org/usage_pulls/daily/2026-06-16.csv" + }, + { + "ReportType": "usage_pulls", + "Cadence": "daily", + "Date": "2026-06-15", + "SizeBytes": 51003, + "Key": "my-org/usage_pulls/daily/2026-06-15.csv" + } + ], + "next_page_token": "" +} +``` + +### Pagination + +Results are paginated with a default page size of 30 and a maximum of 100. +Use the `page_size` and `page_token` query parameters to control pagination. + +```console +$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=10" \ + -H "Authorization: Bearer $TOKEN" | jq . +``` + +When `next_page_token` is non-empty, pass it as `page_token` to fetch the next +page: + +```console +$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=10&page_token=NEXT_TOKEN" \ + -H "Authorization: Bearer $TOKEN" | jq . +``` + +## Download a report + +Download the CSV file for a specific date. The API responds with a `302` +redirect to a pre-signed URL. With `curl -L`, the redirect is followed +automatically and the file is saved locally. + +```console +$ curl -L -o "usage_pulls_2026-06-16.csv" \ + "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily/2026-06-16/download" \ + -H "Authorization: Bearer $TOKEN" +``` + +The pre-signed download URL expires after 15 minutes. If the link expires, +call the endpoint again to get a fresh URL. + +### Download the latest report + +Combine the list and download steps to always fetch the most recent report: + +```bash +DATE=$( + curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=1" \ + -H "Authorization: Bearer $TOKEN" \ + | jq -r '.reports[0].Date // empty' +) + +if [ -z "$DATE" ]; then + echo "No reports available." + exit 1 +fi + +curl -L -o "usage_pulls_${DATE}.csv" \ + "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily/${DATE}/download" \ + -H "Authorization: Bearer $TOKEN" +``` + +## Get report schema + +Retrieve the schema for a specific report date. The schema describes the columns +in the CSV file. + +```console +$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily/2026-06-16/schema" \ + -H "Authorization: Bearer $TOKEN" | jq . +``` + +Example response: + +```json +{ + "category": "usage_pulls", + "fields": [ + { + "name": "date", + "type": "string", + "description": "The date of the pull event (YYYY-MM-DD)." + }, + { + "name": "repository", + "type": "string", + "description": "The repository that was pulled." + }, + { + "name": "pull_count", + "type": "integer", + "description": "Number of pulls for the repository on this date." + } + ] +} +``` + +Use the schema endpoint to programmatically discover column names and types +before processing a report. + +## API reference + +| Endpoint | Description | +|---|---| +| `GET /enterprise-data/v1/orgs/{org}/reports` | List available report types | +| `GET /enterprise-data/v1/orgs/{org}/reports/{type}/{cadence}` | List reports with pagination | +| `GET /enterprise-data/v1/orgs/{org}/reports/{type}/{cadence}/{date}/download` | Download a report (302 redirect) | +| `GET /enterprise-data/v1/orgs/{org}/reports/{type}/{cadence}/{date}/schema` | Get report column schema | + +For the full API specification, see the +[Enterprise Data API reference](/reference/api/enterprise-data/latest/). + +## Troubleshooting + +### 401 Unauthorized + +Your token is missing or invalid. Verify that you are passing the token as a +Bearer token in the `Authorization` header and that the token has not expired. + +### 403 Forbidden + +The authenticated user or token does not have permission to access reports for +this organization. Verify that: + +- The user has the organization owner role or a custom role with the + **report-read** permission. +- The organization has an active Docker Business subscription. + +### 404 Not Found + +The requested report type, cadence, or date does not exist. Use the list +endpoints to discover available reports before attempting a download. diff --git a/content/reference/api/enterprise-data/_index.md b/content/reference/api/enterprise-data/_index.md new file mode 100644 index 00000000000..ef1625f7873 --- /dev/null +++ b/content/reference/api/enterprise-data/_index.md @@ -0,0 +1,5 @@ +--- +title: Enterprise Data API +build: + render: never +--- diff --git a/content/reference/api/enterprise-data/changelog.md b/content/reference/api/enterprise-data/changelog.md new file mode 100644 index 00000000000..4564ec9c499 --- /dev/null +++ b/content/reference/api/enterprise-data/changelog.md @@ -0,0 +1,22 @@ +--- +description: Docker Enterprise Data API changelog +title: Docker Enterprise Data API changelog +linkTitle: Changelog +keywords: docker enterprise, data api, whats new, release notes, api, changelog +weight: 2 +toc_min: 1 +toc_max: 2 +--- + +Here you can learn about the latest changes, new features, bug fixes, and known +issues for the Docker Enterprise Data API. + +--- + +## 2026-06-17 + +### New + +- Initial release of the Enterprise Data API +- Usage reports endpoints: list report types, list reports, download, schema +- Authentication via Personal Access Tokens (PAT) and Organization Access Tokens (OAT) diff --git a/content/reference/api/enterprise-data/deprecated.md b/content/reference/api/enterprise-data/deprecated.md new file mode 100644 index 00000000000..4fd4227b05b --- /dev/null +++ b/content/reference/api/enterprise-data/deprecated.md @@ -0,0 +1,26 @@ +--- +description: Deprecated Docker Enterprise Data API endpoints +keywords: deprecated +title: Deprecated Docker Enterprise Data API endpoints +linkTitle: Deprecated +weight: 3 +--- + +This page provides an overview of endpoints that are deprecated in the Docker Enterprise Data API. + +## Endpoint deprecation policy + +As changes are made to the Docker Enterprise Data API there may be times when existing endpoints need to be removed or replaced with newer endpoints. Before an existing endpoint is removed it is labeled as "deprecated" within the documentation. After some time it may be removed. + +## Deprecated endpoints + +The following table provides an overview of the current status of deprecated endpoints: + +**Deprecated**: the endpoint is marked "deprecated" and should no longer be used. +The endpoint may be removed, disabled, or change behavior in a future release. + +**Removed**: the endpoint was removed, disabled, or hidden. + +--- + +No endpoints are currently deprecated. diff --git a/content/reference/api/enterprise-data/latest.md b/content/reference/api/enterprise-data/latest.md new file mode 100644 index 00000000000..69828067932 --- /dev/null +++ b/content/reference/api/enterprise-data/latest.md @@ -0,0 +1,7 @@ +--- +layout: api +description: Reference documentation and OpenAPI specification for the Docker Enterprise Data API. +title: Docker Enterprise Data API reference +linkTitle: Latest +weight: 1 +--- diff --git a/content/reference/api/enterprise-data/latest.yaml b/content/reference/api/enterprise-data/latest.yaml new file mode 100644 index 00000000000..f31d4cd05ee --- /dev/null +++ b/content/reference/api/enterprise-data/latest.yaml @@ -0,0 +1,511 @@ +openapi: "3.0.3" + +info: + title: Docker Enterprise Data API + version: "1" + description: | + HTTP+JSON API for accessing Docker Enterprise customer usage reports. + + **Overview.** Docker Enterprise subscribers can retrieve structured usage + reports (CSV) covering product activity within their organization. Reports + are generated on a fixed cadence (for example, daily or weekly) and stored + for a retention period. This API provides programmatic access to discover + available report types, list generated reports, download report files, and + inspect report schemas. + + **Resource model.** An organization has one or more report types, each + produced at a specific cadence. Each report type + cadence combination + contains a series of dated report files (CSV). Every report file has an + accompanying JSON schema describing its columns. + + **Authentication.** All endpoints require a Bearer token: an Organization + Access Token (OAT) with the `Report Read` scope. Personal Access Tokens + (PATs) are not supported. + + **Subscription.** An active Docker Enterprise subscription is required. + Requests from organizations without an eligible subscription receive a + `403 Forbidden` response. + + **Pagination.** The list-reports endpoint supports cursor-based pagination + via `page_size` and `page_token` query parameters. Reports are returned + most-recent-first. + contact: + name: Docker + url: https://api.docker.com/ + +tags: + - name: report-types + description: Discover available report type and cadence combinations. + - name: reports + description: List and download generated report files. + - name: schemas + description: Inspect the column schema for a specific report. + +servers: + - url: https://api.docker.com/enterprise-data/v1 + +security: + - bearerAuth: [] + +paths: + /orgs/{org_name}/reports: + parameters: + - $ref: "#/components/parameters/OrgName" + get: + operationId: listReportTypes + tags: [report-types] + summary: List report types + description: > + Returns the distinct report type and cadence combinations available for + the organization. Each entry represents a category of reports that can + be listed and downloaded. + responses: + "200": + description: Array of report type and cadence combinations. + content: + application/json: + schema: + type: object + required: [report_types] + properties: + report_types: + type: array + items: + $ref: "#/components/schemas/ReportTypeInfo" + examples: + default: + value: + report_types: + - ReportType: usage_pulls + Cadence: daily + - ReportType: usage_pulls + Cadence: weekly + - ReportType: image_access + Cadence: daily + "401": + $ref: "#/components/responses/Unauthenticated" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "500": + $ref: "#/components/responses/InternalError" + + /orgs/{org_name}/reports/{type}/{cadence}: + parameters: + - $ref: "#/components/parameters/OrgName" + - $ref: "#/components/parameters/ReportType" + - $ref: "#/components/parameters/Cadence" + get: + operationId: listReports + tags: [reports] + summary: List reports + description: > + Returns a paginated list of available report files for the given report + type and cadence. Reports are sorted most-recent-first. Use `page_size` + and `page_token` query parameters for pagination. + parameters: + - name: page_size + in: query + required: false + description: > + Number of reports to return per page. Minimum 1, maximum 100. + Defaults to 30. + schema: + type: integer + format: int32 + minimum: 1 + maximum: 100 + default: 30 + examples: + default: + value: 30 + - name: page_token + in: query + required: false + description: > + Opaque cursor returned in `next_page_token` from a previous + response. Omit for the first page. + schema: + type: string + examples: + default: + value: "MjAyNi0wNi0wMQ" + responses: + "200": + description: Paginated list of reports. + content: + application/json: + schema: + type: object + required: [reports, next_page_token] + properties: + reports: + type: array + items: + $ref: "#/components/schemas/Report" + next_page_token: + type: string + description: > + Opaque cursor for fetching the next page. Empty string + when there are no more results. + examples: + default: + value: + reports: + - ReportType: usage_pulls + Cadence: daily + Date: "2026-06-16" + SizeBytes: 524288 + Key: my-org/usage_pulls/daily/2026-06-16.csv + - ReportType: usage_pulls + Cadence: daily + Date: "2026-06-15" + SizeBytes: 498712 + Key: my-org/usage_pulls/daily/2026-06-15.csv + next_page_token: "MjAyNi0wNS0xOA" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "500": + $ref: "#/components/responses/InternalError" + + /orgs/{org_name}/reports/{type}/{cadence}/{date}/download: + parameters: + - $ref: "#/components/parameters/OrgName" + - $ref: "#/components/parameters/ReportType" + - $ref: "#/components/parameters/Cadence" + - $ref: "#/components/parameters/Date" + get: + operationId: getReportDownloadURL + tags: [reports] + summary: Download report + description: > + Returns a `302 Found` redirect to a pre-signed S3 URL for the report + CSV file. The pre-signed URL expires after 15 minutes. Follow the + redirect to download the file directly from S3. + + + Most HTTP clients follow redirects automatically. If your client does + not, read the `Location` header from the 302 response and issue a + separate GET to that URL (no Authorization header needed for the + pre-signed URL). + responses: + "302": + description: > + Redirect to a pre-signed download URL. The `Location` header + contains the S3 pre-signed URL. The URL expires after 15 minutes. + headers: + Location: + description: Pre-signed S3 URL for the CSV report file. + schema: + type: string + format: uri + example: "https://customer-exports-prod.s3.amazonaws.com/my-org/usage_pulls/daily/2026-06-16.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&..." + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "500": + $ref: "#/components/responses/InternalError" + + /orgs/{org_name}/reports/{type}/{cadence}/{date}/schema: + parameters: + - $ref: "#/components/parameters/OrgName" + - $ref: "#/components/parameters/ReportType" + - $ref: "#/components/parameters/Cadence" + - $ref: "#/components/parameters/Date" + get: + operationId: getReportSchema + tags: [schemas] + summary: Get report schema + description: > + Returns the JSON schema for the specified report. The schema describes + the columns (fields) present in the CSV file, including each field's + name, data type, and description. Use this to understand the report + structure before or after downloading the CSV. + responses: + "200": + description: Report schema describing the CSV columns. + content: + application/json: + schema: + $ref: "#/components/schemas/ReportSchema" + examples: + default: + value: + category: usage_pulls + fields: + - name: event_date + type: date + description: Date the pull occurred (UTC). + - name: repository + type: string + description: Full repository name including namespace. + - name: tag + type: string + description: Image tag that was pulled. + - name: pull_count + type: integer + description: Number of pulls for this repository and tag on this date. + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "500": + $ref: "#/components/responses/InternalError" + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: | + An Organization Access Token (OAT) passed in the + `Authorization: Bearer ` header. The OAT must have the + **Report Read** scope selected under Organization permissions. + + Personal Access Tokens (PATs) are not supported. + + The organization must have an active Docker Enterprise subscription. + + parameters: + OrgName: + name: org_name + in: path + required: true + description: Docker organization name (the billing entity). + schema: + type: string + pattern: "^[a-z0-9][a-z0-9_-]*$" + examples: + default: + value: my-org + + ReportType: + name: type + in: path + required: true + description: > + Report type identifier. Only lowercase alphanumeric characters, hyphens, + and underscores are allowed. + schema: + type: string + pattern: "^[a-z0-9][a-z0-9_-]*$" + examples: + default: + value: usage_pulls + + Cadence: + name: cadence + in: path + required: true + description: > + Report cadence (for example, `daily` or `weekly`). Only lowercase + alphanumeric characters, hyphens, and underscores are allowed. + schema: + type: string + pattern: "^[a-z0-9][a-z0-9_-]*$" + examples: + default: + value: daily + + Date: + name: date + in: path + required: true + description: > + Report date in `YYYY-MM-DD` format. Identifies a specific report + within the type and cadence. + schema: + type: string + format: date + examples: + default: + value: "2026-06-16" + + schemas: + ReportTypeInfo: + type: object + description: A distinct report type and cadence combination available for the organization. + required: [ReportType, Cadence] + properties: + ReportType: + type: string + description: Report type identifier (for example, `usage_pulls`). + examples: + - usage_pulls + Cadence: + type: string + description: Report generation cadence (for example, `daily`, `weekly`). + examples: + - daily + + Report: + type: object + description: Metadata for a single generated report file. + required: [ReportType, Cadence, Date, SizeBytes, Key] + properties: + ReportType: + type: string + description: Report type identifier. + examples: + - usage_pulls + Cadence: + type: string + description: Report generation cadence. + examples: + - daily + Date: + type: string + format: date + description: Report date in `YYYY-MM-DD` format. + examples: + - "2026-06-16" + SizeBytes: + type: integer + format: int64 + description: Size of the CSV file in bytes. + examples: + - 524288 + Key: + type: string + description: S3 object key for the report file. + examples: + - my-org/usage_pulls/daily/2026-06-16.csv + + ReportSchema: + type: object + description: Schema describing the columns present in a report CSV file. + required: [category, fields] + properties: + category: + type: string + description: Report category (matches the report type). + examples: + - usage_pulls + fields: + type: array + description: Ordered list of columns in the CSV file. + items: + $ref: "#/components/schemas/SchemaField" + + SchemaField: + type: object + description: A single column definition within a report schema. + required: [name, type, description] + properties: + name: + type: string + description: Column name as it appears in the CSV header row. + examples: + - event_date + type: + type: string + description: > + Data type of the column (for example, `string`, `integer`, `date`, + `timestamp`, `boolean`, `float`). + examples: + - string + description: + type: string + description: Human-readable description of what the column contains. + examples: + - Date the pull occurred (UTC). + + Error: + type: object + description: Error envelope returned on all non-2xx responses. + required: [error] + properties: + error: + type: string + description: Human-readable error message. + examples: + - "not found" + + responses: + BadRequest: + description: > + The request contains invalid parameters. Path segments must match + `^[a-z0-9][a-z0-9_-]*$` and dates must be valid `YYYY-MM-DD` values. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + invalid_segment: + summary: Invalid path segment + value: + error: "invalid input: type contains invalid characters" + invalid_date: + summary: Invalid date + value: + error: "invalid input: date must be a valid YYYY-MM-DD date" + invalid_page_token: + summary: Invalid page token + value: + error: "invalid input: invalid page token" + + Unauthenticated: + description: Missing or invalid Bearer token. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + default: + value: + error: unauthenticated + + Forbidden: + description: > + The caller lacks the `OrganizationReportRead` permission for this + organization, or the organization does not have an active Docker + Enterprise subscription. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + default: + value: + error: permission denied + + NotFound: + description: > + The requested resource does not exist. This may mean the organization + has no reports, the report type or cadence is unknown, or the specific + dated report has not been generated. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + default: + value: + error: not found + + InternalError: + description: Unexpected server error. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + default: + value: + error: internal error