Skip to content

The PDF Report API allows API clients to asynchronously generate a downloadable PDF report for a connected SQR user. The flow is fully async: a job is enqueued immediately and processed in the background. Once the job completes, a time-limited pre-signed download URL is issued on demand.

All three endpoints are authenticated using a Bearer token obtained from the OAuth Token API.


How It Works

Generating a PDF report is a three-step asynchronous process:

1. POST /v1/document/api        → Enqueue a report job (returns 202 + jobId)
2. GET  /v1/document/api/{id}   → Poll until status is COMPLETE or FAILED
3. GET  /v1/document/api/{id}/url → Retrieve the signed download URL

Step 1 — Create a Report Job

POST /v1/document/api

Submit a request to generate a PDF report for a specific user. The API responds immediately with 202 Accepted and returns a jobId. No report has been generated yet at this point; the job is placed in a processing queue.

Rate limit: Max 10 requests per 10 minutes per org.

Request

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Body

{
  "userId": "US1A2B3C4D5E6F78"
}
FieldTypeRequiredDescription
userIdstringYesThe SQR user ID (AppUser.id) for whom the report is being generated. Must be 1–16 characters.

Response — 202 Accepted

{
  "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "PENDING",
  "userId": "US1A2B3C4D5E6F78",
  "createdAt": "2025-05-05T10:00:00.000Z",
  "updatedAt": "2025-05-05T10:00:00.000Z"
}

Store the jobId — you will need it to check job status and retrieve the download URL.


Step 2 — Poll Job Status

GET /v1/document/api/{id}

Returns the current status and metadata of the report generation job. Poll this endpoint until status reaches a terminal state: COMPLETE or FAILED.

Request

Headers

Authorization: Bearer <access_token>

Path parameter

ParameterTypeDescription
idstringThe jobId returned in Step 1

Response — 200 OK

{
  "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "COMPLETE",
  "userId": "US1A2B3C4D5E6F78",
  "templateVersion": "v2",
  "sizeBytes": 204800,
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "durationMs": 1420,
  "createdAt": "2025-05-05T10:00:00.000Z",
  "updatedAt": "2025-05-05T10:00:02.000Z",
  "completedAt": "2025-05-05T10:00:02.000Z"
}

Job Status Values

StatusDescription
PENDINGJob is queued and waiting to be processed
IN_PROGRESSJob is currently being processed
COMPLETEReport generated successfully — download URL available
FAILEDReport generation failed — see errorCode

Polling Recommendation

Poll at a reasonable interval to avoid unnecessary load. A recommended strategy is:

  • Poll every 3–5 seconds for the first 30 seconds.
  • If still not complete, back off to every 10–15 seconds.
  • Treat any job that has not completed within 5 minutes as failed and surface an appropriate error to your user.

Step 3 — Retrieve the Signed Download URL

GET /v1/document/api/{id}/url

Once the job status is COMPLETE, request a time-limited pre-signed S3 URL to download the PDF report.

  • The URL is valid for 5 minutes from the time it is issued.
  • RBAC and org scope are re-validated on every call — URLs are never cached server-side.
  • If the report is not yet complete, the API returns 422 Unprocessable Entity.

Request

Headers

Authorization: Bearer <access_token>

Path parameter

ParameterTypeDescription
idstringThe jobId returned in Step 1

Response — 200 OK

{
  "url": "https://s3.amazonaws.com/sqr-reports/...?X-Amz-Signature=...",
  "expiresInSeconds": 300,
  "filename": "SQR_J_Smith_ABCD.pdf"
}
FieldTypeDescription
urlstringPre-signed S3 download URL, valid for 5 minutes
expiresInSecondsnumberURL TTL in seconds (always 300)
filenamestringSuggested filename to use when saving the PDF

Use the url value to initiate a direct download from S3. The URL will expire after expiresInSeconds seconds and cannot be re-used. If you need to allow another download after expiry, simply call this endpoint again to receive a fresh URL.


Error Reference

Status CodeMeaning
401Missing or invalid Bearer token. Obtain a new token via the OAuth Token API.
403Forbidden. The authenticated org does not have permission to access this user's report.
404The specified userId (Step 1) or jobId (Steps 2–3) was not found.
409A pending job already exists for this user. Wait for it to complete before creating a new one.
422The report job is not yet complete (Step 3 only). Continue polling Step 2.
429Rate limit exceeded. Maximum 10 requests per 10 minutes per org (Step 1 only).
5XXInternal server error. Contact support@sqr.id.

Full Example Flow

# Step 1 — Create the job
POST /v1/document/api
Host: api.sqr-group.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "userId": "US1A2B3C4D5E6F78"
}

# → 202 Accepted
# {
#   "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
#   "status": "PENDING",
#   ...
# }

---

# Step 2 — Poll until COMPLETE
GET /v1/document/api/3fa85f64-5717-4562-b3fc-2c963f66afa6
Host: api.sqr-group.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

# → 200 OK
# {
#   "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
#   "status": "COMPLETE",
#   ...
# }

---

# Step 3 — Get the download URL
GET /v1/document/api/3fa85f64-5717-4562-b3fc-2c963f66afa6/url
Host: api.sqr-group.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

# → 200 OK
# {
#   "url": "https://s3.amazonaws.com/...",
#   "expiresInSeconds": 300,
#   "filename": "SQR_J_Smith_ABCD.pdf"
# }