Copy page

Copy page as Markdown for LLMs

View as Markdown

View this page as plain text


Open in ChatGPT

Ask ChatGPT about this page

Open in Claude

Ask Claude about this page

Western Reports V2 API

Generate detailed, fully branded PDF and HTML Western astrology reports. Reports are generated asynchronously: you receive the URLs immediately and the report is ready within 10 to 30 seconds. Each report family supports four depth tiers, so the same birth data can produce anything from a short snapshot to a comprehensive book.


Base URL

https://pdf.divineapi.com

Authentication

Every request requires two headers:

HeaderDescription
AuthorizationBearer {api_acc_token} - identifies the user
x-api-keyUse api_key for live mode, test_api_key for test mode

Live mode deducts from remaining_credits. Test mode deducts from remaining_test_credits.


Generate Report

POST /api/v1/western/reports/generate

How It Works

  1. Send a POST request with birth data + branding - receive reportId + URLs immediately (status: processing)
  2. Report generates in the background (10-30 seconds)
  3. Poll GET /api/v1/reports/:reportId/status until status is completed
  4. HTML and PDF URLs are ready to view/download

Request Headers

Content-Type: application/json
Authorization: Bearer {api_acc_token}
x-api-key: {api_key}

Request Body Parameters

Every parameter accepted by the Western Reports endpoint, with its allowed values. A field you do not send is never touched. Out of range numeric values are clamped rather than rejected, and invalid body_background, cover_pattern or colour values are ignored rather than rejected, so the report still renders without that piece.

1. Report selection

FieldValuesNotes
report_typeA family code (see Available Reports)Required. Send the family code together with tier. Legacy full tier slugs still work.
tiersnapshot | insight | advanced | comprehensiveDefault comprehensive. Omitting it gives the comprehensive report.
report_nameUser inputCover title. Defaults to the report's own name.

2. End user birth data (all required)

FieldValuesNotes
full_nameUser input
day1 to 31
month1 to 12
year1900 to 2100
hour0 to 23
min0 to 59
sec0 to 59
gendermale | femaleLowercase.
placeUser inputFor example "New York, USA"
latUser input numberFor example 40.7128
lonUser input numberFor example -74.006
tzoneUser input numberHours offset, for example -4
lanen (default). Also available: es | pt | de | fr | it | ru

3. Report specific inputs (only the reports named)

FieldValuesNotes
horoscope_month1 to 12Required for western-monthly-horoscope only. Rejected with 422 on every other report.
horoscope_yearUser input, integer yearRequired for western-monthly-horoscope and western-yearly-horoscope. Rejected with 422 everywhere else. The yearly report takes no month.

4. Company branding (all required)

company_name, company_url, company_email, company_mobile, company_bio, footer_text and logo_url are all user input. logo_url must be a PNG or JPEG image URL.

5. Colours (hex #RRGGBB)

FieldDefaultPurpose
theme_color#af1f0fAccents, table headers, borders and all derived artwork
heading_color#af1f0fSection heading text
text_primary_color#000000Body text
text_secondary_color#fff6d3Secondary text
background_color#fff6d3Page background

6. Typography

FieldValuesNotes
font_pairingclassic | modern | elegant | professional | minimal | boldDefault classic
heading_scale0.8 to 1.6Default 1

7. Theme

A one shot preset that sets font, cover, backgrounds and sizing together: classic | editorial | celestial | atelier | almanac | botanic | nocturne. Anything you also send explicitly overrides the theme. A theme never touches your colours, branding, logo or report name. Omit it for the standard look.

8. Cover page

FieldValuesNotes
cover_presethero | centered | vertical | rightcol | portraitShorthand for the three switches below
cover_alignleft | center | rightDefault center
cover_arrangestandard | verticalDefault standard
logo_posleft | center | rightDefault center
cover_modenight | light | brandDefault night. Dark, pale, or follow your colour cover.
cover_patternnone | nebula | aurora | dusk | ember | inkCover artwork tinted from theme_color
cover_backgroundUser input image URLFull bleed cover photo
cover_overlay0 to 100Darkening scrim over a cover photo or pattern
front_imageUser input image URLCover centre image
front_image_size20 to 95 (% of page width)Default 58
cover_title_size0.7 to 2.2Default 1
cover_meta_size0.7 to 1.8Default 1
logo_size0.7 to 2.0Default 1
cover_kickerUser input (supports tokens)Small line above the title
cover_subtitleUser input (supports tokens)Line below the title

Cover tokens for the kicker and subtitle: {name}, {dob}, {tob}, {place}, {company}, {report_name}. An empty token drops its whole segment, including the separator.

9. Body pages

FieldValuesNotes
section_stylestripe | banded | minimalOmit for a plain heading with a rule
vibrancysubtle | balanced | boldDefault balanced. Only affects stripe.
label_pilltrue | falseDefault false. Data section titles as solid pills.
page_footertrue | falseDefault false. Report name and page number in the footer.
body_backgroundnone or a design ID (see below)
body_background_strength0 to 100Default 100. Artwork opacity.
body_image_urlUser input image URLYour own body page artwork
body_image_url_altUser input image URLAlternates on even pages
body_background_modefull | edgesDefault full
body_scrim0 to 100Default 60. Paper veil over the reading band.

body_background design IDs (40):

Celestial: astrolabe | lunation | constellation | orrery | corona | starchart

Geometric: aurora | meridian | sunburst | lattice | chevron | meander

Flowing: contour | marble | crossbed | herbarium | taproot | tidal | ribbon

Washes: horizon | nebula | prism | godray | gloaming | boreal | bleed

Minimal: rule | bracket | rail | ell | solstice | tessera | stele

Printed: halftone | guilloche | riso | woodcut | laid | dogear | signature

10. Advanced and less common

FieldValuesNotes
house_systemP (Placidus) and other standard house system codesDefault P. House division system.
chart_styleObjectNatal wheel appearance, an optional nested object
source_report_idUser input, a prior report idOptional reuse for upsells. Must be the same person, and the same month and year for horoscopes, otherwise 400.
lockedtrue | falseOptional. Locks the call to action and footer link.

Example Request

curl -X POST "https://pdf.divineapi.com/api/v1/western/reports/generate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {api_acc_token}" \
  -H "x-api-key: {api_key}" \
  -d '{
  "report_type": "western-natal-blueprint",
  "tier": "comprehensive",
  "full_name": "Alex Rivera",
  "day": 14,
  "month": 6,
  "year": 1990,
  "hour": 10,
  "min": 25,
  "sec": 0,
  "gender": "male",
  "place": "New York, USA",
  "lat": 40.7128,
  "lon": -74.006,
  "tzone": -4,
  "lan": "en",
  "theme_color": "#8a2b52",
  "heading_color": "#3a1f38",
  "text_primary_color": "#241a2e",
  "text_secondary_color": "#fff6d3",
  "background_color": "#f7f1e8",
  "font_pairing": "classic",
  "heading_scale": 1,
  "report_name": "The Natal Blueprint",
  "cover_kicker": "{company} presents",
  "cover_subtitle": "Prepared for {name} - {dob} - {place}",
  "company_name": "Astro Insights",
  "footer_text": "(c) 2026 Astro Insights - All rights reserved",
  "company_bio": "Astro Insights has guided over 40,000 seekers with personalised readings since 2016.",
  "company_email": "hello@astroinsights.co",
  "company_mobile": "+1 (415) 555-0132",
  "company_url": "https://astroinsights.co",
  "cover_pattern": "none",
  "cover_mode": "night",
  "cover_preset": "hero",
  "cover_align": "left",
  "cover_arrange": "standard",
  "logo_pos": "left",
  "cover_title_size": 1,
  "cover_meta_size": 1,
  "logo_size": 1,
  "front_image_size": 58,
  "label_pill": false,
  "page_footer": false,
  "body_background_strength": 100,
  "section_style": "stripe",
  "vibrancy": "balanced",
  "logo_url": "https://astroinsights.co/logo.png"
}'

Success Response

{
  "reportId": "f8624bc3-71d8-4e72-bd95-895a9778fbd1",
  "htmlUrl": "https://pdf.divineapi.com/reports/html/84cd6e30.html?token=6adf39ad...",
  "pdfUrl": "https://pdf.divineapi.com/reports/pdfs/84cd6e30.pdf?token=df2746fe...",
  "statusUrl": "https://pdf.divineapi.com/api/v1/reports/f8624bc3-.../status?token=a1b2c3d4...",
  "status": "processing"
}
FieldDescription
reportIdUnique report identifier
htmlUrlURL to view the HTML report
pdfUrlURL to download the PDF report
statusUrlURL to poll for report completion status
statusInitial status (processing)

Error Responses

Missing Branding Fields (422)

If any required branding fields are missing:

{
  "error": "Missing required branding fields",
  "details": [
    "Please enter company name",
    "Please enter company url",
    "Please enter company email",
    "Please enter company mobile number",
    "Please enter company bio",
    "Please enter footer text",
    "Please enter logo url"
  ]
}

Invalid Color Format (400)

{
  "error": "Invalid color format for theme_color. Must be hex (#RRGGBB)."
}

Authentication Failed (401)

{
  "error": "Bearer token required"
}
{
  "error": "x-api-key header required"
}
{
  "error": "API key does not match authenticated user"
}

Insufficient Credits (402)

{
  "error": "Insufficient credits"
}

Rate Limit Exceeded (429)

{
  "error": "Rate limit exceeded. Maximum 100 reports per hour."
}

Check Report Status

GET /api/v1/reports/:reportId/status?token={token}

Poll this endpoint to check when a report is ready. The statusUrl is returned by the generate endpoint - use it directly.

Response

{
  "reportId": "f8624bc3-71d8-4e72-bd95-895a9778fbd1",
  "status": "completed",
  "htmlUrl": "https://pdf.divineapi.com/reports/html/84cd6e30.html?token=6adf39ad...",
  "pdfUrl": "https://pdf.divineapi.com/reports/pdfs/84cd6e30.pdf?token=df2746fe..."
}
StatusDescription
processingReport is being generated
completedReport is ready - HTML and PDF URLs are accessible

Available Reports

There are 11 Western report families. Send the family code in report_type together with a tier. The bare family code on its own gives the comprehensive tier, and legacy full tier slugs still work.

CodeReportLanguagesTiers
western-natal-blueprintNatal Blueprinten (English)snapshot, insight, advanced, comprehensive
western-love-signatureLove Signatureen (English)snapshot, insight, advanced, comprehensive
western-dating-mating-relatingDating, Mating & Relatingen (English)snapshot, insight, advanced, comprehensive
western-inner-moonYour Inner Moonen (English)snapshot, insight, advanced, comprehensive
western-career-moneyCareer & Moneyen (English)snapshot, insight, advanced, comprehensive
western-creators-spotlightThe Creator's Spotlighten (English)snapshot, insight, advanced, comprehensive
western-purpose-healingPurpose & Healingen (English)snapshot, insight, advanced, comprehensive
western-year-aheadYear Aheaden (English)snapshot, insight, advanced, comprehensive
western-saturn-returnThe Saturn Return Guideen (English)snapshot, insight, advanced, comprehensive
western-monthly-horoscopeMonthly Horoscopeen (English)snapshot, insight, advanced, comprehensive Also requires horoscope_month and horoscope_year.
western-yearly-horoscopeYearly Horoscopeen (English)snapshot, insight, advanced, comprehensive Also requires horoscope_year.

Tiers. Every family accepts an optional tier parameter that sets how deep the report goes: snapshot (shortest), insight, advanced, or comprehensive (fullest). If you do not send tier, the report is generated as comprehensive. Credit cost per report: snapshot 50, insight 100, advanced 150, comprehensive 200.

Languages. Pass the language in lan. English (en) is the default; es, pt, de, fr, it and ru are also available.

Font Pairings

ValueStyle
classicTraditional serif headings with clean body text
modernContemporary sans-serif throughout
elegantDecorative headings with refined body text
professionalBusiness-appropriate font combination
minimalClean, lightweight fonts
boldStrong, impactful heading fonts

Rate Limits

EndpointLimit
POST /reports/generate100 requests per hour per client
GET /reports/:id/status300 requests per minute per IP

Complete Flow Example

Step 1: Generate Report

curl -X POST https://pdf.divineapi.com/api/v1/western/reports/generate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {api_acc_token}" \
  -H "x-api-key: {api_key}" \
  -d '{
    "report_type": "western-natal-blueprint",
    "full_name": "Priya Singh",
    "day": 22,
    "month": 3,
    "year": 1995,
    "hour": 8,
    "min": 15,
    "sec": 0,
    "gender": "female",
    "place": "Mumbai, India",
    "lat": 19.0760,
    "lon": 72.8777,
    "tzone": 5.5,
    "lan": "en",
    "company_name": "Astro Insights",
    "company_url": "https://astroinsights.com",
    "company_email": "info@astroinsights.com",
    "company_mobile": "+91 9876543210",
    "company_bio": "Your trusted source for Western astrology.",
    "footer_text": "© 2026 Astro Insights",
    "logo_url": "https://astroinsights.com/logo.png"
  }'

Response

{
  "reportId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "htmlUrl": "https://pdf.divineapi.com/reports/html/xyz.html?token=abc123...",
  "pdfUrl": "https://pdf.divineapi.com/reports/pdfs/xyz.pdf?token=def456...",
  "statusUrl": "https://pdf.divineapi.com/api/v1/reports/f8624bc3-.../status?token=a1b2c3d4...",
  "status": "processing"
}

Step 2: Poll Status (wait for completion)

curl https://pdf.divineapi.com/api/v1/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status?token=abc123...

Response (while generating)

{
  "reportId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "statusUrl": "https://pdf.divineapi.com/api/v1/reports/f8624bc3-.../status?token=a1b2c3d4...",
  "status": "processing"
}

Response (when ready)

{
  "reportId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "completed",
  "htmlUrl": "https://pdf.divineapi.com/reports/html/xyz.html?token=abc123...",
  "pdfUrl": "https://pdf.divineapi.com/reports/pdfs/xyz.pdf?token=def456..."
}

Step 3: Download or Display

  • Open htmlUrl in a browser to view the interactive HTML report
  • Open pdfUrl to download or embed the PDF report
curl -X POST "https://pdf.divineapi.com/api/v1/western/reports/generate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {Your Auth Token}" \
  -H "x-api-key: {Your API Key}"
const axios = require('axios');

const response = await axios.post(
  'https://pdf.divineapi.com/api/v1/western/reports/generate',
  {},
  {
  headers: {
      'Content-Type': "application/json",
      'Authorization': "Bearer {Your Auth Token}",
      'x-api-key': "{Your API Key}",
    },
}
);

console.log(response.data);
import requests

url = "https://pdf.divineapi.com/api/v1/western/reports/generate"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer {Your Auth Token}",
    "x-api-key": "{Your API Key}",
}

response = requests.post(url, headers=headers)

print(response.json())
const response = await fetch(
  'https://pdf.divineapi.com/api/v1/western/reports/generate',
  {
    method: 'POST',
    headers: {
        'Content-Type': "application/json",
        'Authorization': "Bearer {Your Auth Token}",
        'x-api-key': "{Your API Key}",
      },
  }
);

const data = await response.json();
console.log(data);
<?php

use GuzzleHttp\Client;

$client = new Client();

$response = $client->request('POST', 'https://pdf.divineapi.com/api/v1/western/reports/generate', [
    'headers' => [
        'Content-Type' => 'application/json',
        'Authorization' => 'Bearer {Your Auth Token}',
        'x-api-key' => '{Your API Key}',
    ],
]);

echo $response->getBody();
package main

import (
    "fmt"
    "net/http"
    "io"
)

func main() {
    req, _ := http.NewRequest("POST", "https://pdf.divineapi.com/api/v1/western/reports/generate", nil)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer {Your Auth Token}")
    req.Header.Set("x-api-key", "{Your API Key}")

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    body2, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body2))
}
import okhttp3.*;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        OkHttpClient client = new OkHttpClient();

        RequestBody body = null;

        Request request = new Request.Builder()
            .url("https://pdf.divineapi.com/api/v1/western/reports/generate")
            .post(body)
            .addHeader("Content-Type", "application/json")
            .addHeader("Authorization", "Bearer {Your Auth Token}")
            .addHeader("x-api-key", "{Your API Key}")
            .build();

        Response response = client.newCall(request).execute();
        System.out.println(response.body().string());
    }
}
import Foundation

let url = URL(string: "https://pdf.divineapi.com/api/v1/western/reports/generate")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer {Your Auth Token}", forHTTPHeaderField: "Authorization")
request.setValue("{Your API Key}", forHTTPHeaderField: "x-api-key")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let data = data {
        print(String(data: data, encoding: .utf8) ?? "")
    }
}
task.resume()
import okhttp3.*

fun main() {
    val client = OkHttpClient()

    val body: RequestBody? = null

    val request = Request.Builder()
        .url("https://pdf.divineapi.com/api/v1/western/reports/generate")
        .post(body!!)
        .addHeader("Content-Type", "application/json")
        .addHeader("Authorization", "Bearer {Your Auth Token}")
        .addHeader("x-api-key", "{Your API Key}")
        .build()

    client.newCall(request).execute().use { response ->
        println(response.body?.string())
    }
}
using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", "Bearer {Your Auth Token}");
        client.DefaultRequestHeaders.Add("x-api-key", "{Your API Key}");

        var response = await client.PostAsync("https://pdf.divineapi.com/api/v1/western/reports/generate");
        var result = await response.Content.ReadAsStringAsync();
        Console.WriteLine(result);
    }
}