Developers
SDKs, Postman Collection, and Code Examples
Ready-made clients for the SafetyDataSheetAPI extraction endpoints. Each is a single file with no dependencies, so there is nothing to install from a package registry.
Version 1.0.0 · Last updated: 2026-10-24 · Contract: /openapi.yaml · Reference: API docs
Downloads
| Tool | Requires | Download |
|---|---|---|
| Python client | Python 3.9+, standard library only | safetydatasheetapi.py |
| JavaScript client | Node.js 18+ (or any runtime with fetch and FormData) | safetydatasheetapi.mjs |
| Postman collection | Postman 10+ or Newman | safetydatasheetapi.postman_collection.json |
| OpenAPI 3.1 contract | Any OpenAPI tooling or code generator | openapi.yaml |
Both clients cover single extraction, bulk jobs with Idempotency-Key, job polling, typed errors (including Retry-After on rate limits), and webhook signature verification. If you need another language, generate a client from the OpenAPI contract.
Authentication and endpoints
Send your API key as Authorization: Bearer <api_key> (the clients do this for you). Request a key with the self-serve signup; the free sample upload on the homepage needs no key. Keep keys out of source control and client-side code.
Enterprise customers receive a dedicated deployment with its own base URL. Both clients take it as an option: Client(api_key=..., base_url="https://your-dedicated-url") in Python and new Client({ apiKey, baseUrl }) in JavaScript, and the Postman collection has a baseUrl variable.
curl
Single document
curl -X POST "https://safetydatasheetapi.com/extract-sds" \
-H "Authorization: Bearer $SDS_API_KEY" \
-F "[email protected]" \
-F "language_hint=en"
Bulk job with a webhook
curl -X POST "https://safetydatasheetapi.com/extract-sds/bulk" \
-H "Authorization: Bearer $SDS_API_KEY" \
-H "Idempotency-Key: nightly-refresh-2026-10-24" \
-F "[email protected]" \
-F "[email protected]" \
-F "callback_url=https://example.com/hooks/sds"
curl "https://safetydatasheetapi.com/extract-sds/bulk/<job_id>" \
-H "Authorization: Bearer $SDS_API_KEY"
Python
curl -O https://safetydatasheetapi.com/sdk/python/safetydatasheetapi.py
import os
from safetydatasheetapi import Client, ApiError, RateLimitError
client = Client(api_key=os.environ["SDS_API_KEY"])
try:
result = client.extract("acetone-sds.pdf", language_hint="en")
except RateLimitError as error:
print("Rate limited. Retry in", error.retry_after, "seconds")
raise
except ApiError as error:
print(error.status, error.code, error.request_id)
raise
record = result["outputs"]["json"]
print(result["confidence_score"], record["product_identification"]["product_name"])
# Bulk: submit, then wait (or pass callback_url= to receive a signed webhook instead)
job = client.submit_bulk(["acetone-sds.pdf", "toluene-sds.pdf"], idempotency_key="nightly-2026-10-24")
done = client.wait_for_bulk_job(job["job_id"])
for item in done["items"]:
print(item["file_name"], item["status"])
Verify a webhook
Every webhook carries X-Webhook-Signature: sha256=<hmac>, the HMAC-SHA256 of the raw JSON body. Always verify before trusting the payload.
from safetydatasheetapi import verify_webhook_signature
# body must be the raw bytes of the request, before JSON parsing
ok = verify_webhook_signature(WEBHOOK_SECRET, request_body_bytes, headers["X-Webhook-Signature"])
JavaScript
curl -O https://safetydatasheetapi.com/sdk/node/safetydatasheetapi.mjs
import { Client, ApiError, RateLimitError } from "./safetydatasheetapi.mjs";
const client = new Client({ apiKey: process.env.SDS_API_KEY });
try {
const result = await client.extract("acetone-sds.pdf", { languageHint: "en" });
const record = result.outputs.json;
console.log(result.confidence_score, record.product_identification.product_name);
} catch (error) {
if (error instanceof RateLimitError) console.log("Retry in", error.retryAfter, "seconds");
else if (error instanceof ApiError) console.log(error.status, error.code, error.requestId);
throw error;
}
// Bulk: submit, then wait (or pass callbackUrl to receive a signed webhook instead)
const job = await client.submitBulk(["acetone-sds.pdf", "toluene-sds.pdf"], { idempotencyKey: "nightly-2026-10-24" });
const done = await client.waitForBulkJob(job.job_id);
for (const item of done.items) console.log(item.file_name, item.status);
Verify a webhook
import { verifyWebhookSignature } from "./safetydatasheetapi.mjs";
// rawBody must be the exact string or Buffer received, before JSON parsing
const ok = verifyWebhookSignature(process.env.WEBHOOK_SECRET, rawBody, req.headers["x-webhook-signature"]);
Postman
- In Postman choose Import and paste
https://safetydatasheetapi.com/postman/safetydatasheetapi.postman_collection.json. - Open the collection's Variables tab and set
apiKey.baseUrldefaults to the hosted API; set it to your dedicated URL if you have an enterprise deployment. - Run Extract one SDS and choose a PDF in the
filefield. - Run Submit bulk job, then Get bulk job status. The job id is carried over automatically.
Each request includes saved example responses (success, 401, 429, 502) and test scripts. To run it headless: newman run safetydatasheetapi.postman_collection.json --env-var apiKey=$SDS_API_KEY.
AI agents: MCP server and skill
AI assistants can use the API directly through a remote Model Context Protocol server at https://safetydatasheetapi.com/mcp (Streamable HTTP). Listing the tools is open; calling them needs your API key as Authorization: Bearer <api_key>.
claude mcp add --transport http safetydatasheetapi https://safetydatasheetapi.com/mcp \
--header "Authorization: Bearer $SDS_API_KEY"
| Tool | What it does |
|---|---|
extract_sds | Extract one PDF (file_url or file_base64) into the normalized record, with confidence_score and warnings. |
submit_bulk_extraction | Submit up to 10 PDFs (file_urls) as one job; supports idempotency_key. |
get_bulk_job | Read job status and per-file results. Read-only. |
get_account | Prepaid balance, price per document and the last 30 days of usage. Read-only; needs a per-customer key. |
The MCP server uses the same authentication, rate limits, and error codes as the REST API. File URLs must be public https addresses. An agent skill with usage guidance and safety rules is published at /.well-known/agent-skills/safetydatasheetapi/SKILL.md, indexed in index.json. Machine-readable details: MCP manifest, protected resource metadata.
Handling errors
Every error uses one envelope, {"ok": false, "error": {"code", "message"}}. Branch on error.code; the clients expose it as code. On a 429, wait Retry-After seconds. Server-side failures carry a request_id: quote it when contacting support. See the full list in the error table.
Versioning and changes
The clients follow the API's versioning and deprecation policy. Changes to the clients or the API are announced in the changelog.