docs: add Enterprise Data API reference and usage reports guide by cassio-paesleme · Pull Request #25383 · docker/docs · GitHub
Skip to content

docs: add Enterprise Data API reference and usage reports guide#25383

Draft
cassio-paesleme wants to merge 10 commits into
docker:mainfrom
cassio-paesleme:cassio/enterprise-data-api-docs
Draft

docs: add Enterprise Data API reference and usage reports guide#25383
cassio-paesleme wants to merge 10 commits into
docker:mainfrom
cassio-paesleme:cassio/enterprise-data-api-docs

Conversation

@cassio-paesleme

Copy link
Copy Markdown

Summary

  • Adds OpenAPI 3.0 spec and API reference page for the Docker Enterprise Data API at /reference/api/enterprise-data/
  • Adds feature guide for enterprise usage reports at /manuals/enterprise/reports/

Context

Docker Enterprise subscribers will be able to programmatically export organization usage reports (pull data) via api.docker.com/enterprise-data/v1/. This is a new API surface, separate from the Hub API, supporting both PAT and OAT authentication.

Related PRs:

New pages

Path Description
/reference/api/enterprise-data/api.yaml OpenAPI 3.0 spec (4 endpoints: list types, list reports, download, schema)
/reference/api/enterprise-data/index.md API reference landing page
/manuals/enterprise/reports/_index.md Feature guide with auth setup, curl walkthrough, pagination, troubleshooting

Test plan

  • API reference renders correctly at /reference/api/enterprise-data/
  • Feature guide renders in the Enterprise sidebar
  • curl examples are copy-pasteable and accurate

🤖 Generated with Claude Code

Add documentation for the Docker Enterprise Data API, which provides
programmatic access to organization usage reports (CSV) via
api.docker.com/enterprise-data/v1/.

- reference/api/enterprise-data/ — OpenAPI 3.0 spec and rendered API
  reference page for all four endpoints (list types, list reports,
  download, schema)
- manuals/enterprise/reports/ — feature guide with authentication
  setup (PAT and OAT flows), curl walkthrough, pagination, and
  troubleshooting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Jun 17, 2026

Copy link
Copy Markdown

Deploy Preview for docsdocker ready!

Name Link
🔨 Latest commit 89508df
🔍 Latest deploy log https://app.netlify.com/projects/docsdocker/deploys/6a3c221fb3cc6c000877feec
😎 Deploy Preview https://deploy-preview-25383--docsdocker.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the area/api Relates to Docker API docs label Jun 17, 2026

@docker-agent docker-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🔴 CRITICAL

Two newly added documents (the OpenAPI spec and the feature guide) describe different URL structures for the same API endpoints. One of them is wrong, and users will get 404 errors following whichever document is incorrect.

- bearerAuth: []

paths:
/orgs/{org_name}:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] OpenAPI spec paths missing /reports segment — inconsistent with guide

The OpenAPI spec defines the listReportTypes endpoint at /orgs/{org_name} (full URL: https://api.docker.com/enterprise-data/v1/orgs/{org_name}), but the feature guide and the API reference table both consistently use /orgs/{org}/reports as the list-report-types path. The same mismatch applies across all four endpoints:

OpenAPI spec path Guide/table path
GET /orgs/{org_name} GET /orgs/{org}/reports
GET /orgs/{org_name}/{type}/{cadence} GET /orgs/{org}/reports/{type}/{cadence}
GET /orgs/{org_name}/{type}/{cadence}/{date}/download GET /orgs/{org}/reports/{type}/{cadence}/{date}/download
GET /orgs/{org_name}/{type}/{cadence}/{date}/schema GET /orgs/{org}/reports/{type}/{cadence}/{date}/schema

One of these is wrong. If the actual API requires /reports in the path (as the guide shows), users using the spec for client generation or manual calls will get 404 errors. If the spec is correct, every curl example in the guide will fail.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c8fe0a6. Added the missing /reports segment to all four OpenAPI spec paths. They now match the guide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thank you! Confirmed that all four paths now include /reports and align with the guide. The spec is now consistent and will generate correct client code.

Discover which report types and cadences are available for your organization.

```console
$ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] curl examples include /reports path segment not present in OpenAPI spec

All curl examples in this guide include /reports in the path (e.g., /orgs/$ORG/reports, /orgs/$ORG/reports/usage_pulls/daily), but the OpenAPI spec defines paths without this segment (e.g., /orgs/{org_name}, /orgs/{org_name}/{type}/{cadence}).

Both documents are new and were published together, yet they describe different URL structures. Please reconcile: either add the missing /reports segment to all four paths in api.yaml, or remove it from the guide's curl examples and reference table to match the spec.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c8fe0a6. The OpenAPI spec paths now include /reports and match the curl examples.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thank you! I verified the commit and all four paths in the OpenAPI spec now correctly include "/reports" to match the curl examples and documentation. The discrepancy is resolved.


```bash
DATE=$(
curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=1" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Download-latest script silently produces broken output when no reports exist

When the API returns an empty reports list, jq -r '.reports[0].Date' outputs the literal string null (not an empty string). The script then silently:

  • Creates a file named usage_pulls_null.csv
  • Makes a download request to .../daily/null/download, which returns a 404

Consider adding a guard to catch this case:

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"

Using // empty makes jq output nothing (empty string) instead of null, so the shell check [ -z "$DATE" ] works correctly for both the no-reports and API-error cases.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e983461. Added // empty to the jq expression and a shell guard that exits early with a message when no reports are available.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Thanks for the quick fix. The guard now correctly handles the empty reports case and prevents the script from creating broken files.

cassio-paesleme and others added 7 commits June 17, 2026 14:20
The spec paths were missing the /reports segment, making them
inconsistent with the curl examples in the guide and the actual
REST handler routes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use jq's // empty alternative operator so an empty report list
produces an empty string instead of the literal "null". Add a
shell guard to exit early with a message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the Enterprise Data API reference to match the sidebar
pattern used by Docker Hub API and DVP Data API:
- _index.md as hidden section index (build: render: never)
- latest.md with layout: api pointing to latest.yaml
- changelog.md with initial release entry
- deprecated.md with empty deprecation table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per IAM team guidance, PATs cannot be scoped outside of registry.
OATs are the only supported auth mechanism for the Reports API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -0,0 +1,238 @@
---
title: Usage reports

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage reports should go under Admin > Organizations, rather than the top level categories. I'll open this up and make some editorial changes.

@akristen akristen self-assigned this Jun 22, 2026
- 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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `jq` installed for JSON parsing (optional, for formatting responses)

- One of the following:
- Organization owner role
- A custom role that includes the **report-read** permission
- `curl` installed for making API requests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `curl` installed for making API requests


## Authentication

The Reports API requires an Organization Access Token (OAT). OATs are

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move into pre-reqs to replace curl/jq prereqs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically some guidance around having available OATs, since some orgs have limitations; they need an open OAT slot to create a new one (if I'm understanding correctly)

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turn into tip call out in prereqs

- `curl` installed for making API requests
- `jq` installed for JSON parsing (optional, for formatting responses)

## Authentication

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Authentication
## Set up OAT for Reports API

You use this `TOKEN` value in the `Authorization: Bearer` header for all
subsequent API calls.

## List available report types

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## List available report types
## List reports


## List available report types

Discover which report types and cadences are available for your organization.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Discover which report types and cadences are available for your organization.
You can fetch report types and their cadences on a per-organization basis. For example, you can fetch all available reports to your organization, or you can fetch a scoped set of reports by time interval.


Discover which report types and cadences are available for your organization.

```console

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```console
### List all available reports
```console

-H "Authorization: Bearer $TOKEN" | jq .
```

Example response:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per style guide, let's make this a complete sentence. For example:

Suggested change
Example response:
An example response will describe the report types and cadence. This response tells you that your organization has usage pull reports set to a daily cadence.

}
```

Each entry represents a distinct combination of report type and cadence. Use

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Each entry represents a distinct combination of report type and cadence. Use
Each entry represents a distinct combination of report type and cadence. If you have more report types or different cadences configured, you can find that information here. Use

Each entry represents a distinct combination of report type and cadence. Use
these values in subsequent calls.

## List reports

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## List reports
### List reports by type and cadence


## List reports

List available reports for a given type and cadence. Reports are returned in

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
List available reports for a given type and cadence. Reports are returned in
Based off the response to the list available reports query, you can list reports by type and cadence. Reports are returned in

## List reports

List available reports for a given type and cadence. Reports are returned in
reverse chronological order (most recent first).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
reverse chronological order (most recent first).
reverse chronological order so the most recent are listed first.

-H "Authorization: Bearer $TOKEN" | jq .
```

Example response:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some additional explanation in complete sentence form, per style guide

-H "Authorization: Bearer $TOKEN" | jq .
```

## Download a report

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Download a report
## Download reports

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a ToC POV, we want these specific actions to be nested and balanced for better visibility. We should add a sentence at minimum that describes why it's best practice to download a report, what you might use it for, and generalized information that's scattered in the below h3s. for example, this would be the place we say reports are downloaded as CSVs.


## Download a report

Download the CSV file for a specific date. The API responds with a `302`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Download the CSV file for a specific date. The API responds with a `302`
### Download specific reports
Download the CSV file for a specific date. The API responds with a `302`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super happy you included a troubleshooting section!

@akristen akristen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cassio-paesleme Thanks so much for filing this PR. I've made some comments for myself to act on when I implement a review.

If you could go through and tell me what you think about these suggestions before I start implementing, that would be amazing. :) I will handle all changes on my end since they're mostly editorial in nature and you already did the hard work of generating a draft.

Feel free to ping me on Slack for any questions / and a back and forth, as well as when you'd like this PR out. The main blocker is moving "Usage Reports" under "Admin > Org" so it's on the same level as Activity Logs and Insights. 🫡

cassio-paesleme and others added 2 commits June 24, 2026 11:25
The raw OAT cannot be used directly as a Bearer token. It must first
be exchanged for a JWT via the Hub auth endpoint. Added the exchange
step and a note about JWT expiry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api Relates to Docker API docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants