documentation
API Reference
Full reference for the push endpoint and authentication
Authentication
All API requests require a bearer token in the Authorization header:
Authorization: Bearer <your-token>
Tokens are project-scoped — a token from project A cannot push to project B. To generate a token, open the project in your dashboard, then Project Settings, then API Tokens.
POST /api/push
Submit a bundle snapshot. The format is auto-detected from the request body structure.
Request
POST https://dendrobundle.com/api/push
Headers
| Header | Value |
|---|---|
Authorization |
Bearer (required) |
Content-Type |
application/json (required) |
Content-Encoding |
gzip (optional) — gzip-compress the body. Recommended for large stats files; they compress ~10–20×, keeping uploads well under the size limit. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
branch |
string | Branch name. Max 255 chars. Optional but recommended. |
commit |
string | Full 40-character commit SHA. Optional but recommended. |
Body
Raw bundle stats JSON in any supported format. The body is parsed and the format detected automatically based on the top-level structure:
{ "dendrobundle": 1, assets }→ generic-json (explicit marker — checked first)[{ label, parsedSize|statSize, groups }](root array) → webpack-bundle-analyzer report{ results }→ source-map-explorer{ tree, nodeParts, nodeMetas }→ rollup-stats (rollup-plugin-visualizer; also covers Vite){ inputs, outputs }→ esbuild-metafile{ assets, chunks, rspackVersion }→ rspack-stats{ assets, chunks, modules }→ webpack-stats{ buildTime, bundles }→ parcel-metrics (@parcel/reporter-build-metrics)
Size & compression. The decompressed body may be up to 32 MB by default (self-hosted deployments can raise it via MAX_PUSH_BODY_BYTES). Send Content-Encoding: gzip and gzip the body for large stats files — the server inflates it transparently. Oversized payloads receive a 413.
Response
200 OK — snapshot recorded successfully.
{
"snapshotId": "snap_01j9x2k4m8p3q7r5t6w9y2z0",
"format": "webpack-stats",
"totalSizeBytes": 2528604,
"assetCount": 23
}
| Field | Type | Description |
|---|---|---|
snapshotId |
string | Unique identifier for the snapshot |
format |
string | Detected format (webpack-stats, rspack-stats, esbuild-metafile, source-map-explorer, rollup-stats, webpack-bundle-analyzer, parcel-metrics, generic-json) |
totalSizeBytes |
number | Sum of all asset sizes in bytes |
assetCount |
number | Number of distinct output assets |
400 Bad Request — unrecognized format or malformed JSON.
{
"error": "Could not parse bundle stats: unrecognized or malformed format. Supported: webpack-stats, rspack-stats, esbuild-metafile, source-map-explorer, rollup-stats, webpack-bundle-analyzer, parcel-metrics, generic-json (see docs/formats)."
}
401 Unauthorized — missing or invalid token.
{ "error": "invalid token" }
409 Conflict — this commit was already pushed in this format for this project. Dedup is per (commit, format): the same commit may be pushed once per stats format (e.g. webpack + esbuild + rollup for one build), and each lands as its own snapshot. Untagged pushes (no ?commit) are never deduped.
{ "error": "commit already tracked for this format" }
413 Payload Too Large — body exceeds the size limit (32 MB decompressed by default). gzip the body, or split the stats.
{ "error": "Payload too large" }
429 Too Many Requests — rate limit exceeded.
{ "error": "rate limit exceeded" }
Rate limits
The push endpoint allows 60 requests per minute per token. Requests over the limit receive a 429 response with a Retry-After header (seconds until the window resets). For normal CI usage — one push per build — you will never see this limit.
Snapshot retention
Retention follows your account plan:
| Plan | History |
|---|---|
| Community | Rolling 10 most recent snapshots per project — older ones are pruned on each push |
| Developer | Unlimited |
Example
curl -sS \
"https://dendrobundle.com/api/push?branch=main&commit=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-d @dist/webpack-stats.json
Large files — gzip the body (recommended above a few MB):
gzip -c dist/webpack-stats.json | curl -sS \
"https://dendrobundle.com/api/push?branch=main&commit=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" \
-H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
-H "Content-Type: application/json" \
-H "Content-Encoding: gzip" \
--data-binary @-