Evidence
API Changelog
Dated changes to the SafetyDataSheetAPI endpoints, response contract, and documentation. Deprecation notices are announced here first, following the deprecation lifecycle.
Last updated: 2026-10-23 · Machine-readable contract: /openapi.yaml
2026-10-25
- Added: Buy credit by card in the dashboard (Billing): packs of $25, $100 and $500, priced in USD, GBP or EUR through Stripe, with VAT added where it applies, a VAT number field for businesses and an invoice for every payment. Purchased credit is valid for 12 months; unused credit expires after that and the dashboard warns before it does. Credit is spent soonest-expiring first.
- Added: Per-customer API keys (
sds_live_...) with a prepaid credit balance. Each document is billed at $0.25 per 40 pages (rounded up) from the balance; failed extractions are not billed. New error codes:402 insufficient_credit(balance, required amount, pages and documents billed are returned besideerror),413 too_many_pages(limit 400 pages),401 api_key_revokedand403 account_suspended. Successful responses to per-customer keys carry abillingobject. Keys are limited per key (60 requests a minute by default). - Added:
GET /api/accountand the MCP toolget_accountreturn the balance, price and 30-day usage for the key's account. MCP server version 1.1.0. - Changed: Keys issued before this release (the shared enterprise key) keep working unmetered.
2026-10-24
- Added:
document_languagein single-extraction responses, at the top level and inmetadata: the language the document is written in, detected from the document (for examplesvorpt-BR), ornullwhen it cannot be determined. It is separate fromlanguage_hint, which only echoes the hint you sent. Bulk job items do not carry it yet. - Changed: Transient failures of the extraction service (temporary unavailability, rate limiting, or an unreadable answer) are now retried up to twice before a
provider_erroris returned. Requests that are invalid, blocked, or cut off at an output limit are not retried. - Added: A fixed output schema (version 1.0: 16 sections, about 100 fields including storage class, water hazard class, VOC content, SVHC substances and per-mode transport data) can be enforced for a deployment. When it is on,
outputs.jsonalways has exactly the same keys in the same order, missing values arenull,metadata.schema_versionis1.0, and responses carryis_safety_data_sheet; non-SDS documents are flagged with a warning. It is on for all extractions as of 2026-10-24. - Added:
schema_versioncan be sent as a form field to pin the output schema; only1.0is supported and any other value returns400 unsupported_schema_version. Responses now includeschema_versionat the top level, and bulk items includedocument_languageandschema_version. The fixed schema is now on for all extractions. Example values such as2026-01that appeared in older documentation are not valid. - Fixed: A response from the extraction model that stopped before finishing (for example at an output limit) now returns a
provider_errorinstead of partial data. - Changed: The extraction request is now deterministic (temperature 0) and instructs the model to copy text verbatim and include every list item and table row. This is aimed at shortened output and run-to-run differences; it does not by itself fix field-name variation inside sections, which needs a fixed schema (planned).
- Added: Remote MCP server at
https://safetydatasheetapi.com/mcp(Streamable HTTP, stateless) with toolsextract_sds,submit_bulk_extraction, andget_bulk_job. Same API key, rate limits, and error codes as the REST API. See SDKs and agents. - Added: Agent skill (discovery index), OAuth protected resource metadata, an
x-agentic-accesssection and a typedwebhooksdefinition (bulk_extraction.completed) in the OpenAPI contract. - Security: Webhook
callback_urlvalidation is stricter: it now rejects IPv6 literals, link-local and cloud-metadata addresses, the whole 127.0.0.0/8 range, carrier-grade NAT, reserved ranges, single-label and internal host names, and URLs with embedded credentials. - Added: Official clients and Postman collection: a single-file Python client, a single-file JavaScript client, and a Postman collection with saved examples and test scripts. Each covers single extraction, bulk jobs with
Idempotency-Key, job polling, typed errors withRetry-After, and webhook signature verification. - Removed: The
providerobject (name,model) is no longer returned in successful extraction responses. It identified the upstream model vendor, was not part of the documented output contract, and is not needed to consume results. Clients that read it should stop; no other response fields changed. - Security: Server-side failures (
provider_error,provider_not_configured,output_processing_failed) now return a generic message and arequest_idonly. They no longer include upstream provider names, raw provider responses, configuration hints, or internal exception text. This also applies to failed items in bulk job status and webhook payloads. Theprovider_status,provider_error,provider_hint,provider_response, andprovider_model_attemptsfields are removed from error bodies. - Docs: Bulk job items now document
error_codeanderror_message, and the job documentswebhook_attempts.
2026-10-23
- Added: Provider-published discovery files: /apis.yml, /.well-known/apis.json, and an RFC 9727 /.well-known/api-catalog, also advertised from the homepage in a
Link: rel="api-catalog"header. - Fixed: Unknown URLs (including unknown
/.well-known/*paths) returned200with the homepage HTML. They now return a proper404. - Added:
Retry-Afterheader (seconds) on every429 rate_limitedresponse, alongside the existingretry_after_epoch_secondsbody field. - Docs: openapi.yaml rewritten as OpenAPI 3.1 with a shared error envelope, rate-limit headers, both auth schemes, and request/response examples.
- Docs: The spec no longer claims
application/xmlortext/csvresponses from/extract-sds. It always returns JSON, with XML and CSV insideoutputs. This describes existing behavior; no API behavior changed. - Docs: The API docs error table now lists the codes the API actually returns, and a rate limits section was added.
- Docs: Example URLs now use
https://safetydatasheetapi.com/extract-sds. The separateapi.safetydatasheetapi.comhost never resolved and was removed from the docs and spec.
2026-09-16
- Added: Asynchronous bulk extraction:
POST /extract-sds/bulk(up to 10 files,202with a job id) andGET /extract-sds/bulk/{jobId}, with optional signed webhook delivery (X-Webhook-Signature),Idempotency-Keysupport, and per-file and per-job size limits. - Fixed: Intermittent raw
502responses on the sample upload flow. Failures while formatting extraction output now return a clean500 output_processing_failedJSON error. - Security:
/extract-sdsnow fails closed (503) when no API key is configured; stricter bot verification and rate limiting on website endpoints; CSV output neutralizes spreadsheet formula injection; PDF signature validation on uploads. - Privacy: Removed a third-party visitor-tracking script from all pages.
- Added: Self-serve API access signup on the homepage.
Deprecations
No fields or endpoints are currently deprecated. Future deprecations will be listed here on day 0 with a migration mapping and a removal date, and honor the support windows in the schema versioning policy.