Skip to content
API96Astro API

API reference / PDF jobs

PDF jobs

Render any report capability as a branded PDF in the background: submit a job, poll it, then download the file from its signed link.

3 operations. Submitting and polling take your key in the Authorization header; the download link needs none. Instead of polling, a webhook can tell you when a job finishes. Schemas come from the OpenAPI document; the walk-through is in the PDF jobs and webhooks guide.

Render a report as a PDF

POST

https://api.96astro.com/v1/jobs/pdf

Queues a PDF of any report capability. The response is 202 with the job; poll GET /v1/jobs/{job_id} until status is succeeded, then download download_url. Branding is optional. Sandbox keys get a SANDBOX watermark, 5 PDFs a day, free.

Credits
The report's own credits + 120 (report-career: 10 credits + 120)
Charged
Reserved when the job is accepted (meta.credits_reserved), kept on success, released if it fails. Re-downloading is free.
Sandbox
Free, 5 PDF jobs a day, with a SANDBOX watermark
Response
202 Accepted with the job; its URL in the Location header
Headers
HeaderValue and description
AuthorizationRequiredBearer YOUR_API_KEY

Your sandbox (sk_test_...) or live (sk_live_...) key. X-API-Key: <key> is accepted instead.

Content-TypeRequiredapplication/json

The body is JSON.

Idempotency-KeyOptional<unique string>

Makes retries safe: a repeated key with the same body replays the stored response and is never charged twice. (1 to 200 characters)

Body · application/json
FieldDescription
capabilitystringRequired

A report capability id, e.g. report-marriage. Its own credits are charged too.

Allowed values:
32 valuesbnn-graha-phalaclassical-kundli-reportdetailed-lifelal-kitab-predictionlongevity-analysismatching-reportprediction-bhaveshprediction-classicsprediction-dashaprediction-gemprediction-life-reportprediction-lucky-infoprediction-nakshatra-interpprediction-natureprediction-physicalprediction-planetary-dispositionsreport-careerreport-childrenreport-educationreport-foreign-travelreport-healthreport-marriagereport-politicsreport-propertyreport-relocationreport-romancereport-spiritualreport-wealthsynastry-fullsynastry-predictionswestern-detailed-reportwestern-yearly-forecast

Example: report-career

inputobjectRequired

That capability's request body, exactly as for POST /v1/{family}/{capability}.

brandingobject | nullOptional

Optional branding. Without it the PDF is plain.

Default: null

branding.brand_namestring | nullOptional

Printed on the cover and in the running head.

Default: null

Limits: at most 60 characters

Example: Shree Jyotish Kendra

branding.accentstring | nullOptional

Hex colour for headings and rules, e.g. #1f4fd1. Must reach 4.5:1 contrast against white.

Default: null

Example: #1f4fd1

branding.logostring | nullOptional

data:image/png;base64,... or data:image/svg+xml;base64,..., at most 200 KB. SVG is sanitised.

Default: null

Limits: at most 300000 characters

branding.footer_notestring | nullOptional

Printed at the foot of every page.

Default: null

Limits: at most 200 characters

Example: Consultations: jyotish.example

languagestringOptional

Document language. English only for now.

Default: en

Allowed value: en

Example request

Example response

202application/json
{
  "data": {
    "id": "2c863278-518b-407e-8234-0ba0f824404c",
    "object": "job",
    "kind": "pdf",
    "capability": "report-career",
    "status": "queued",
    "attempts": 0,
    "credits": 130,
    "created_at": "2026-10-14T06:58:59.069427Z",
    "started_at": null,
    "finished_at": null,
    "error": null,
    "download_url": null,
    "download_expires_at": null,
    "file_expires_at": null
  },
  "meta": {
    "request_id": "req_84c3f093ee178943738c",
    "api_version": "v1",
    "credits_reserved": 130,
    "warnings": []
  }
}

The example job of the PDF jobs guide; ids, times and the token differ on every job.

Error responses

  • 400invalid_request
  • 401invalid_key, expired_key
  • 402payment_required
  • 403account_suspended
  • 409idempotency_conflict
  • 413payload_too_large
  • 422invalid_request, unsupported_language
  • 429rate_limited, quota_exhausted, spend_cap_reached, project_budget_exceeded
  • 500computation_failed

Errors are never charged. What each status means and what to do: errors.

Poll a job

GET

https://api.96astro.com/v1/jobs/{job_id}

The job's status, timestamps, error and, once it succeeded, a signed download URL. Only the organisation and environment (sandbox or live) that created a job can see it. Free.

Credits
Free: polling is never charged
Rate limit
1 unit per poll; poll every few seconds with backoff, or use a webhook
Status
queued → running → succeeded or failed; expired once the file is deleted
Visible to
Keys of the organization and environment (sandbox or live) that created the job
Headers
HeaderValue and description
AuthorizationRequiredBearer YOUR_API_KEY

Your sandbox (sk_test_...) or live (sk_live_...) key. X-API-Key: <key> is accepted instead.

Path parameters
ParameterDescription
job_idstringRequired

The job's id, from the 202 answer of POST /v1/jobs/pdf (also in its Location header).

Limits: format uuid

Example: 2c863278-518b-407e-8234-0ba0f824404c

Example request

Example response

200application/json
{
  "data": {
    "id": "2c863278-518b-407e-8234-0ba0f824404c",
    "object": "job",
    "kind": "pdf",
    "capability": "report-career",
    "status": "succeeded",
    "attempts": 1,
    "credits": 130,
    "created_at": "2026-10-14T06:58:59.069427Z",
    "started_at": "2026-10-14T06:59:01.112040Z",
    "finished_at": "2026-10-14T06:59:09.874120Z",
    "error": null,
    "download_url": "https://api.96astro.com/v1/files/LIYyeFGLQH6CNAug-CRATAAAAABq0IgA.NynSAx6dDFQT8zUxIyAB2hbRNyymB7qVvTKYY1gdP-Y",
    "download_expires_at": "2026-10-15T08:00:00Z",
    "file_expires_at": "2026-10-21T06:59:09.874120Z"
  },
  "meta": {
    "request_id": "req_1f7a0c93b2d84e6a5c19",
    "api_version": "v1",
    "credits_used": 0,
    "warnings": []
  }
}

The example job of the PDF jobs guide; ids, times and the token differ on every job.

Error responses

  • 401invalid_key, expired_key
  • 403account_suspended
  • 404not_found
  • 429rate_limited, quota_exhausted, spend_cap_reached, project_budget_exceeded

Errors are never charged. What each status means and what to do: errors.

Download a PDF

GETNo API key

https://api.96astro.com/v1/files/{token}

Streams the PDF for a signed token from download_url. Needs no API key. Free.

Credits
Free
Auth
None: the signed token is the credential
Link
Valid 24 hours (download_expires_at); after that 410 link_expired: poll the job for a fresh link
File
Kept 7 days (file_expires_at); after that 410 file_expired: create a new job

Headers

None. Send no Authorization header: the signed token in the URL is the credential, so the link can be handed to an end user's browser.

Path parameters
ParameterDescription
tokenstringRequired

The signed token at the end of the job's download_url. Call download_url exactly as given; it expires at download_expires_at.

Example: LIYyeFGLQH6CNAug-CRATAAAAABq0IgA.NynSAx6dDFQT8zUxIyAB2hbRNyymB7qVvTKYY1gdP-Y

Example request

Example response

200application/pdf
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report-career-2c863278.pdf"
Cache-Control: private, no-store

%PDF-1.7 … (the file's bytes)

The body is the PDF itself; the headers are shown here.

Error responses

  • 404not_found
  • 410link_expired, file_expired

Errors are never charged. What each status means and what to do: errors.