Grounded

API Documentation

The Grounded API is a REST API for submitting PDFs and retrieving preflight results. All endpoints return JSON.

Authentication

Include your API key in the Authorization header:

Authorization: Bearer grd_your_api_key_here

Rate Limits

Rate limits are per-tenant and reset daily at midnight UTC. Check response headers for your current usage:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997

Base URL

https://api.grounded.dev

Endpoints

POST/api/v1/jobsAuth required

Submit a PDF for preflight analysis.

Request

curl -X POST https://api.grounded.dev/v1/jobs \
  -H "Authorization: Bearer grd_..." \
  -F file=@document.pdf \
  -F profile_id=grounded-default

Response

{
  "job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "status": "pending",
  "profile_id": "grounded-default",
  "file_name": "document.pdf",
  "created_at": "2026-03-12T10:30:00Z"
}
GET/api/v1/jobs/{job_id}Auth required

Get job status and results.

Request

curl https://api.grounded.dev/v1/jobs/f47ac10b-... \
  -H "Authorization: Bearer grd_..."

Response

{
  "job_id": "f47ac10b-...",
  "status": "complete",
  "profile_id": "grounded-default",
  "file_name": "document.pdf",
  "file_size": 524288,
  "page_count": 4,
  "created_at": "2026-03-12T10:30:00Z",
  "completed_at": "2026-03-12T10:30:01Z",
  "duration_ms": 1240,
  "summary": {
    "total_findings": 2,
    "no_fly_count": 0,
    "delay_count": 1,
    "advisory_count": 1,
    "passed": true,
    "page_count": 4,
    "file_size_bytes": 524288
  },
  "findings": [
    {
      "inspection_id": "color.spot_color_usage",
      "severity": "delay",
      "message": "Spot color 'PANTONE 185 C' found on page 2",
      "page_num": 2
    }
  ]
}
GET/api/v1/jobsAuth required

List all jobs with pagination.

Request

curl "https://api.grounded.dev/v1/jobs?page=1&page_size=20" \
  -H "Authorization: Bearer grd_..."

Response

{
  "jobs": [...],
  "total": 42,
  "page": 1,
  "page_size": 20
}
DELETE/api/v1/jobs/{job_id}Auth required

Delete a job and its results.

Request

curl -X DELETE https://api.grounded.dev/v1/jobs/f47ac10b-... \
  -H "Authorization: Bearer grd_..."

Response

204 No Content
GET/api/v1/profiles

List available preflight profiles (flight plans).

Request

curl https://api.grounded.dev/v1/profiles

Response

{
  "profiles": [
    {
      "profile_id": "grounded-default",
      "name": "Grounded Default",
      "description": "Standard CMYK preflight with all 196 checks",
      "conformance": null,
      "workflow": "CMYK",
      "is_builtin": true
    }
  ]
}
POST/api/v1/webhooksAuth required

Register a webhook endpoint for job events.

Request

curl -X POST https://api.grounded.dev/v1/webhooks \
  -H "Authorization: Bearer grd_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-app.com/webhook", "events": ["job.completed", "job.failed"]}'

Response

{
  "id": "a1b2c3d4-...",
  "url": "https://your-app.com/webhook",
  "events": ["job.completed", "job.failed"],
  "is_active": true,
  "created_at": "2026-03-12T10:30:00Z"
}

Code Examples

Python

import httpx

client = httpx.Client(
    base_url="https://api.grounded.dev",
    headers={"Authorization": "Bearer grd_..."},
)

# Submit a job
with open("brochure.pdf", "rb") as f:
    resp = client.post("/api/v1/jobs", files={"file": f})
    job = resp.json()

# Poll for results
result = client.get(f"/api/v1/jobs/{job['job_id']}").json()
summary = result.get("summary", {})
print(f"Status: {result['status']}, Findings: {summary.get('total_findings', 0)}")

JavaScript (Node.js)

import fs from "node:fs";

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("brochure.pdf")]));

const resp = await fetch("https://api.grounded.dev/api/v1/jobs", {
  method: "POST",
  headers: { Authorization: "Bearer grd_..." },
  body: form,
});

const job = await resp.json();
console.log("Job ID:", job.job_id);