API reference
The public REST API, operation by operation. The pages are built from the API’s OpenAPI document, so the fields, examples and error codes are the ones the API itself checks and sends.
- Base URL
https://ecdsa.com/api/v1- OpenAPI 3.1 document
- https://ecdsa.com/api/v1/openapi.json
Operations
Signatures
ECDSA signature verification and DER ⇄ raw r‖s conversion.
JWT
Decoding JSON Web Tokens and verifying ES256/ES384/ES512 signatures.
Certificates
X.509 certificate and chain decoding with assessments.
Domain health
TLS signature-health grades of public domains. These operations connect to the domain.
Webhooks
Webhook endpoints of the API key's account and test deliveries. These operations need an API key with the webhooks scope; deliveries are signed with ECDSA P-256 (ES256).
Conventions
Base URL and versions
Every operation lives under https://ecdsa.com/api, followed by its path, such as /v1/verify. The version is part of the path: within v1, answers only ever gain fields and error codes, so ignore members you do not know and treat an unknown code by its HTTP status.
Authentication
None needed: every operation works anonymously. API keys will be optional — sent as Authorization: Bearer … or in the X-API-Key header — and lift a call from the per-IP limit to the key’s own. They arrive with ecdsa.com accounts. A malformed key header is refused with unauthorized rather than ignored.
Requests
POST bodies are JSON objects of at most 100 KB, with arrays and objects nested at most 64 levels deep (JSON documents inside string fields count too). GET operations take their input from the path.
Response headers
The headers the API sends, where they apply:
| Header | What it carries |
|---|---|
| X-Request-Id | Identifier of this request, also quoted in every error body. A caller's own X-Request-Id (1–128 characters of A–Z, a–z, 0–9, '.', '_', ':' and '-') is echoed unless it contains an API key; otherwise one is generated. |
| X-RateLimit-Limit | Requests allowed per window by the limit reported on this response. |
| X-RateLimit-Remaining | Requests left in the current window. |
| X-RateLimit-Reset | Unix time (seconds) at which the current window ends. |
| X-Quota-Limit | Calls made with an API key only: the size of the account's quota that runs out first for this operation — daily or monthly quota units, or daily domain scans. |
| X-Quota-Remaining | Calls made with an API key only: what is left of that quota after this call. |
| X-Quota-Reset | Calls made with an API key only: Unix time (seconds) at which that quota starts over. |
| Retry-After | Seconds to wait before retrying; for quota_exceeded, until the quota starts over. |
| Allow | The methods this path accepts. |
| WWW-Authenticate | The bearer challenge (RFC 6750), e.g. `Bearer realm="ecdsa.com", error="invalid_token"`. |
Errors
A failed call answers with a 4xx or 5xx status and this JSON envelope; the error table lists every code.
| Field | Type | Required | Description |
|---|---|---|---|
| error | object | yes | |
| error.code | string | yes | Machine-readable error code. Each response lists the codes it can carry; new codes may be added within v1, so treat an unknown code by its HTTP status. |
| error.message | string | yes | Human-readable explanation (English). |
| error.requestId | string | no | The X-Request-Id of this request — quote it when reporting a problem. Sent since v1.1. |
| error.detail | object | no | Structured context for the error, such as the offending field; omitted when there is none.
|
| error.docs | string | no | Where the error codes are explained. Sent since v1.1.
|
Rate limits
60 requests per minute per IP across the API, plus 10 per minute for the operations that scan a domain. A 429 answer carries Retry-After.
Private keys
Never send one. A request that contains private-key material anywhere — a PEM PRIVATE KEY block, an OpenSSH, SSH2 or PuTTY key, a JWK with “d” — is refused with private_key_rejected before anything else happens.