-
Notifications
You must be signed in to change notification settings - Fork 8.4k
docs: add Enterprise Data API reference and usage reports guide #25383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
2dd75a2
c8fe0a6
e983461
e335d3c
623c41d
15defd5
85bdbb9
ca54d60
a1e2444
89508df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,262 @@ | ||||||||
| --- | ||||||||
| 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, personal access token, pat, 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/core-subscription/details/) | ||||||||
| - One of the following: | ||||||||
| - Organization owner role | ||||||||
| - A custom role that includes the **report-read** permission | ||||||||
| - `curl` installed for making API requests | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| - `jq` installed for JSON parsing (optional, for formatting responses) | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| ## Authentication | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| The Reports API accepts two authentication methods: Personal Access Tokens (PATs) | ||||||||
| and Organization Access Tokens (OATs). Both are sent directly as Bearer tokens. | ||||||||
|
|
||||||||
| ### Option A: Personal Access Token | ||||||||
|
|
||||||||
| Use a PAT from a user account that has the required role in the organization. | ||||||||
|
|
||||||||
| 1. [Create a personal access token](/security/access-tokens/) with | ||||||||
| **Read-only** access or broader. | ||||||||
|
|
||||||||
| 2. Set your variables: | ||||||||
|
|
||||||||
| ```bash | ||||||||
| ORG="<your-org-name>" | ||||||||
| TOKEN="<your-personal-access-token>" | ||||||||
| ``` | ||||||||
|
|
||||||||
| 3. Test the token: | ||||||||
|
|
||||||||
| ```console | ||||||||
| $ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \ | ||||||||
| -H "Authorization: Bearer $TOKEN" | jq . | ||||||||
| ``` | ||||||||
|
|
||||||||
| ### Option B: Organization Access Token | ||||||||
|
|
||||||||
| Use an OAT issued to the organization. OATs do not require a specific user | ||||||||
| account. | ||||||||
|
|
||||||||
| 1. [Create an organization access token](/security/oat/) with | ||||||||
| the appropriate permissions. | ||||||||
|
|
||||||||
| 2. Set your variables: | ||||||||
|
|
||||||||
| ```bash | ||||||||
| ORG="<your-org-name>" | ||||||||
| TOKEN="<your-organization-access-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 | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| ```console | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| $ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \ | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [HIGH] All Both documents are new and were published together, yet they describe different URL structures. Please reconcile: either add the missing
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in c8fe0a6. The OpenAPI spec paths now include
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||||||||
| -H "Authorization: Bearer $TOKEN" | jq . | ||||||||
| ``` | ||||||||
|
|
||||||||
| Example response: | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
|
||||||||
|
|
||||||||
| ```json | ||||||||
| { | ||||||||
| "report_types": [ | ||||||||
| { | ||||||||
| "ReportType": "usage_pulls", | ||||||||
| "Cadence": "daily" | ||||||||
| } | ||||||||
| ] | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| Each entry represents a distinct combination of report type and cadence. Use | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| these values in subsequent calls. | ||||||||
|
|
||||||||
| ## List reports | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| reverse chronological order (most recent first). | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| ```console | ||||||||
| $ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily" \ | ||||||||
| -H "Authorization: Bearer $TOKEN" | jq . | ||||||||
| ``` | ||||||||
|
|
||||||||
| Example response: | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add some additional explanation in complete sentence form, per style guide |
||||||||
|
|
||||||||
| ```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 | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 the CSV file for a specific date. The API responds with a `302` | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| 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" \ | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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,
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
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in e983461. Added
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||||||||
| -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/). | ||||||||
|
|
||||||||
| ## Troubleshooting | ||||||||
|
|
||||||||
| ### 401 Unauthorized | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Super happy you included a troubleshooting section! |
||||||||
|
|
||||||||
| 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. | ||||||||
There was a problem hiding this comment.
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.