Skip to content
Join Now Login

Upload API

Gaffer’s Upload API allows you to upload test reports from any CI/CD system or local environment. The API accepts multipart form data containing your test report files and optional metadata.

POST https://app.gaffer.sh/api/upload

All requests must include your project’s upload token in the X-API-Key header. You can find your upload token in your project settings.

HeaderDescription
X-API-KeyYour project upload token (required)
Content-Typemultipart/form-data (set automatically by most HTTP clients)

The request body must be multipart/form-data with the following fields:

FieldTypeRequiredDescription
filesFile(s)YesOne or more test report files to upload. Include multiple files by repeating the field.
tagsJSON stringNoMetadata tags as a JSON object (see below).

Tags are optional metadata that help you organize and filter your test runs. Pass them as a JSON string in the tags field.

TagRecommendedDescription
commitShaStrongly recommendedThe git commit SHA associated with this test run.
branchRecommendedThe git branch name (e.g., main, feature/auth).
test_frameworkOptionalThe test framework used (e.g., playwright, jest, pytest).
test_suiteOptionalA label for the test suite (e.g., unit, integration, e2e).

You can also include any custom tags you like. All tag values must be strings.

The single-POST endpoint documented here is capped by the Cloudflare edge at 100 MB total per request.

For files larger than 100 MB (Playwright traces, large videos, full HTML reports), use the gaffer CLI or the gaffer-uploader@v2 GitHub Action instead. Both transparently route uploads through Gaffer’s multipart endpoints, supporting individual files up to 5 GB. Your plan’s storage cap is the only practical ceiling.

Gaffer supports a variety of test report formats:

  • Playwright HTML - Full HTML report with embedded data
  • Vitest HTML - Vitest HTML reporter output
  • Jest JSON - Native Jest JSON output (--json)
  • Jest HTML - jest-html-reporter output
  • pytest HTML - pytest-html plugin output
  • JUnit XML - Standard JUnit XML format
  • Vitest JSON - Vitest JSON reporter output
curl
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: YOUR_UPLOAD_TOKEN" \
-F "files=@playwright-report/index.html" \
-F 'tags={"commitSha":"abc123def456","branch":"main","test_framework":"playwright"}'
curl
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: YOUR_UPLOAD_TOKEN" \
-F "files=@playwright-report/index.html" \
-F "files=@playwright-report/data/test-results.json" \
-F 'tags={"commitSha":"abc123","branch":"feature/auth"}'

A successful upload returns HTTP 201 Created with the following JSON response:

Response
{
"testRun": {
"id": "abc123xyz",
"uniqueId": "1701234567890",
"projectId": "proj_abc123",
"commitSha": "abc123def456",
"branch": "main",
"tags": {
"commitSha": "abc123def456",
"branch": "main",
"test_framework": "playwright"
},
"createdAt": "2024-01-15T10:30:00.000Z"
},
"files": [
{
"filename": "index.html",
"size": 245678,
"path": "org_123/proj_456/1701234567890/index.html",
"contentType": "text/html"
}
]
}
FieldDescription
testRun.idUnique identifier for the test run.
testRun.uniqueIdTimestamp-based identifier.
testRun.projectIdThe project this test run belongs to.
testRun.commitShaGit commit SHA (if provided in tags).
testRun.branchGit branch name (if provided in tags).
testRun.tagsAll tags provided in the request.
testRun.createdAtWhen the test run was created.
filesArray of uploaded file details.
warningsOptional array of warning messages (e.g., if parsing couldn’t be queued).
StatusMeaningDescription
400Bad RequestNo files provided, invalid tags format, or file too large.
401UnauthorizedMissing or invalid upload token.
402Payment RequiredStorage limit exceeded. Upgrade your plan for more storage.
503Service UnavailableTemporary upload failure. Retry the request.