ESGNode Developer API
Run ESGNode's three core features programmatically: Analysis (requirement-by-requirement compliance scoring), Compare (multi-document cross-comparison), and Report Write (AI report generation). Authenticate with an API key; pay per call from a prepaid credit wallet — no per-request checkout.
https://esgnode.com/api/v1/ · All responses are JSON. All work is asynchronous: POST starts a job, GET polls for results.Authentication
Create a key in Settings → Developer API (Professional plan or higher). The raw key is shown once — store it securely. Send it on every request:
Authorization: Bearer esgx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are scoped to one or more permissions: analysis, compare, report. A key without the matching permission gets 403 INSUFFICIENT_PERMISSIONS.
esgx_test_…) run for free and never charge the wallet — use them to integrate before going live.Credits & pricing
Credits are denominated in US dollars. Buy a bundle in the dashboard; the balance is debited per call. Credits never expire.
| Bundle | Price | Credits | Effective rate |
|---|---|---|---|
| Starter | $25 | $25 | 1.00 |
| Growth | $85 | $100 | 0.85 |
| Scale | $320 | $400 | 0.80 |
| Enterprise | $1,125 | $1,500 | 0.75 |
Per-call cost
| Feature | Formula | Minimum |
|---|---|---|
| Analysis | $3 base + $0.04/page (max 600) + $1.50/standard + $1 AI drafts + $0.50 vision | $5.00 |
| Compare | $1.50/document + $2.00/standard | $4.00 |
| Report write | $6 base + $0.25/requirement | $10.00 |
The exact charge is returned as credits_charged_cents in every POST response. A fully-failed job is automatically refunded.
Typical flow
# 1. Upload a PDF → get report_id
curl -s https://esgnode.com/api/v1/upload.php \
-H "Authorization: Bearer $ESGX_KEY" \
-F "file=@sustainability-report.pdf"
# 2. Start an analysis against a standard
curl -s https://esgnode.com/api/v1/analysis.php \
-H "Authorization: Bearer $ESGX_KEY" \
-H "Content-Type: application/json" \
-d '{"report_id":123,"standard_id":7,"ai_drafts":true}'
# 3. Poll until status == "done"
curl -s "https://esgnode.com/api/v1/analysis.php?id=456" \
-H "Authorization: Bearer $ESGX_KEY"
Upload
POST /api/v1/upload.php — permission: analysis or compare. Multipart field file (PDF, up to 100 MB). Free; charge happens at analyze/compare.
{ "error": false, "report_id": 123, "filename": "report.pdf", "page_count": 148 }
Analysis
POST /api/v1/analysis.php — permission: analysis.
{ "report_id": 123, "standard_id": 7, "ai_drafts": true, "vision": false }
Response:
{ "error": false, "analysis_id": 456, "status": "pending",
"credits_charged_cents": 1150, "credits_remaining_cents": 8850 }
GET /api/v1/analysis.php?id=456 — poll. When status is done:
{ "error": false, "analysis_id": 456, "status": "done", "score": 0.74,
"standard": { "id": 7, "name": "GRI Universal Standards" },
"results": [
{ "requirement_id": 12, "code": "GRI 2-1", "title": "Organizational details",
"status": "found", "confidence": 0.91,
"matched_text": "…verbatim quote…", "page": 4, "ai_draft": null }
] }
DELETE /api/v1/analysis.php?id=456 — delete an analysis.
Compare
POST /api/v1/compare.php — permission: compare. Omit standard_id for wildcard (topic-discovery) mode. 2–5 documents.
{ "report_ids": [123, 124, 125], "standard_id": 7 }
GET /api/v1/compare.php?id=789 returns results[] with per-criterion findings when done.
Report write
POST /api/v1/report.php — permission: report. The project must already exist (create it in the dashboard).
{ "project_id": 55 }
GET /api/v1/report.php?id=55 returns status, generation_step, has_output.
Standards
GET /api/v1/standards.php — list available frameworks with requirement counts.
{ "error": false, "standards": [
{ "id": 7, "name": "GRI Universal Standards", "code": "GRI1", "requirement_count": 142 }
] }
Credits endpoint
GET /api/v1/credits.php — current balance + last 20 ledger entries. Works with an API key or a dashboard session.
{ "error": false, "balance_cents": 8850, "balance_usd": 88.5,
"transactions": [ { "delta_cents": -1150, "reason": "analysis",
"reference_id": "report:123", "balance_after": 8850, "created_at": "…" } ] }
Rate limits
| Tier | Per minute | Per day | Concurrent jobs |
|---|---|---|---|
| Default | 10 | 200 | 3 |
| Growth ($100+ lifetime) | 30 | 1,000 | 10 |
| Scale ($400+ lifetime) | 100 | 5,000 | 25 |
Exceeding a limit returns 429 RATE_LIMITED with a Retry-After header.
Errors
All errors share one envelope:
{ "error": true, "code": "INSUFFICIENT_CREDITS",
"message": "Your balance ($0.45) is below the cost of this analysis ($5.00). Top up at /settings?tab=api.",
"balance_cents": 45, "required_cents": 500 }
| Code | HTTP | Meaning |
|---|---|---|
| INVALID_API_KEY | 401 | Missing or malformed key |
| KEY_REVOKED | 401 | Key revoked or expired |
| INSUFFICIENT_PERMISSIONS | 403 | Key lacks the feature permission |
| INSUFFICIENT_CREDITS | 402 | Wallet balance too low |
| RATE_LIMITED | 429 | Too many requests |
| REPORT_NOT_FOUND / ANALYSIS_NOT_FOUND | 404 | Resource missing or not yours |
| VALIDATION_ERROR | 422 | Bad request body |
| SERVER_ERROR | 500 | Unexpected failure |