API REST v1 · gratuita · sin claves · CORS habilitado
API de firmas gratuita
Las comprobaciones que hay detrás de las herramientas de ecdsa.com, invocables desde scripts, CI y agentes de IA: verificar firmas ECDSA, convertir DER ⇄ raw, decodificar y verificar JWT ES256/ES384/ES512, decodificar certificados X.509 y calificar el estado de las firmas TLS de un dominio. JSON simple sobre HTTPS: https://ecdsa.com/api/v1
curl -s https://ecdsa.com/api/v1Especificación legible por máquina: /api/v1/openapi.json (OpenAPI 3.1)
Qué hace la API
Cada operación es una función pura de su entrada: envías JSON y recibes JSON. Cada una tiene una página de referencia con sus campos, un ejemplo ejecutable y sus códigos de error.
- POST/v1/verifyVerify an ECDSA signature
- POST/v1/convertConvert a signature between DER and raw r‖s
- POST/v1/jwt/decodeDecode a JWT (no signature check)
- POST/v1/jwt/verifyVerify an ES256/ES384/ES512 JWT signature
- POST/v1/cert/decodeDecode an X.509 certificate or chain
- GET/v1/health/{domain}TLS signature-health grade for a domain
- GET/v1/webhooksList webhook endpoints
- POST/v1/webhooksCreate a webhook endpoint
- POST/v1/webhooks/deleteDelete a webhook endpoint
- POST/v1/webhooks/testSend a test event
Los agentes de IA y los asistentes de los IDE invocan las mismas operaciones a través del servidor MCP. Referencia completa de la API
Tu primera llamada en 30 segundos
Pega uno de estos fragmentos en una terminal o en la consola de un navegador. El ejemplo es real: la firma se verifica con la clave.
curl -sS 'https://ecdsa.com/api/v1/verify' \
-H 'content-type: application/json' \
-d '{
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4+8TCP3Hop/Acb8L7reksO9flyt1\nsUhvEqUs7a45RVDRDtAIZdTnOJcAhTCQvdzUBO4KUyxSRcZm6ro+2RGfSQ==\n-----END PUBLIC KEY-----",
"message": "The quick brown fox jumps over the lazy dog",
"signature": "3045022100df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24022030c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131"
}'const response = await fetch("https://ecdsa.com/api/v1/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4+8TCP3Hop/Acb8L7reksO9flyt1\nsUhvEqUs7a45RVDRDtAIZdTnOJcAhTCQvdzUBO4KUyxSRcZm6ro+2RGfSQ==\n-----END PUBLIC KEY-----",
"message": "The quick brown fox jumps over the lazy dog",
"signature": "3045022100df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24022030c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131"
}),
});
console.log(response.status, await response.json());{
"valid": true,
"curve": "P-256",
"curvesTried": [
"P-256"
],
"keySource": "pem-spki",
"signatureFormat": "der",
"details": {
"r": "df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24",
"s": "30c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131",
"highS": false
},
"notes": []
}Esta es la respuesta de la API a esta misma solicitud.
Siguiente paso: todos los campos y opciones de esta operación en la referencia de la API, y qué significa cada error en la tabla de errores.
Lo básico
Gratis, sin claves
Sin registro, sin tokens, sin cuotas que gestionar. Envías una solicitud y recibes JSON. Las claves de API opcionales, con límites más altos, llegarán con las cuentas de ecdsa.com.
60 solicitudes/min por IP
Un límite generoso para scripts y CI. La operación de diagnóstico de dominios añade un cupo propio de 10 por minuto, porque escanea hacia el exterior.
CORS abierto
Access-Control-Allow-Origin: * en cada respuesta: llama a la API directamente desde un navegador, una página de documentación o una función serverless.
Nunca envíes claves privadas
Las solicitudes que contienen un bloque PEM PRIVATE KEY, una clave privada de OpenSSH, SSH2 o PuTTY, o una JWK con «d» se rechazan con private_key_rejected. Para cualquier dato secreto, usa las herramientas locales del navegador: nunca transmiten tus datos de entrada.
No se registra nada
Los cuerpos de las solicitudes se analizan en memoria y nunca se escriben en los registros.
Límites de frecuencia
60 solicitudes por minuto por IP en toda la API, más 10 por minuto para /v1/health/{domain}, que abre conexiones TLS salientes.
Cada respuesta incluye X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset; al superar un límite se devuelve 429 con un encabezado Retry-After.
Los escaneos reales de un dominio también consumen cupos compartidos por todos: un mismo host se escanea como máximo 6 veces cada 10 minutos, y todos los escaneos juntos, como máximo 300 veces por minuto, de modo que la API no se puede usar para saturar un servidor. Las respuestas servidas desde la caché de una hora no consumen nada; un escaneo que supera un cupo recibe como respuesta 429 rate_limited y Retry-After.
Con una clave de API, las llamadas se limitan por clave —120 por minuto en el plan gratuito, 600 en el plan Pro— y consumen las cuotas diarias y mensuales de la cuenta. Las claves llegarán con las cuentas de ecdsa.com y todavía no se pueden crear; hasta entonces, todas las llamadas son anónimas.
Se prevé ofrecer más llamadas y monitorización: consulta los precios y únete a la lista de espera.
Considera las cifras documentadas como el cupo previsto, no como un techo estricto: ante un 429, espera con cortesía antes de reintentar y usa tu propia caché; los resultados del diagnóstico de dominios ya se guardan en caché durante una hora.
Errores
Cada error es un JSON con un código legible por máquina y un mensaje legible por personas que dice exactamente qué estaba mal en la entrada: las mismas explicaciones que muestran las herramientas del navegador. Las respuestas de error enlazan a esta página en su campo docs.
| Código | HTTP | Significado |
|---|---|---|
| invalid_json | 400 | The body is not valid JSON or not a JSON object; or the input nests arrays and objects more than 64 levels deep (JSON documents inside string fields count too), or is too complex to inspect for private keys. |
| missing_field | 400 | A required field is absent or empty. |
| invalid_input | 400 | A field could not be parsed — the message explains exactly why. |
| private_key_rejected | 400 | The request contains private-key material (a PEM PRIVATE KEY block, an OpenSSH, SSH2 or PuTTY private key, or a JWK with "d"). Never send private keys anywhere. |
| unsupported_algorithm | 400 | The token's algorithm is not one this operation verifies. |
| invalid_domain | 400 | Not a public DNS hostname (IP addresses, single-label names and paths are refused). |
| scan_dns_error | 400 | The domain does not resolve in public DNS. |
| scan_private_address | 400 | The domain resolves (at least partly) to a private or reserved address. |
| webhook_url_refused | 400 | The webhook URL cannot receive deliveries: it is not https on port 443, its host is not a public DNS name, or the name does not resolve or resolves (at least partly) to a private or reserved address. |
| unauthorized | 401 | The Authorization or X-API-Key header is malformed, the API key is not valid (wrong checksum, unknown, revoked or expired), or the operation needs a key. |
| forbidden_scope | 403 | The API key is valid but lacks a scope this operation requires; the message names it. |
| webhook_limit_reached | 403 | The account already has as many webhook endpoints as its plan allows. |
| not_found | 404 | No operation exists at this path. |
| webhook_not_found | 404 | The API key's account has no webhook endpoint with this id. |
| method_not_allowed | 405 | The path exists but does not accept this HTTP method; see the Allow header. |
| payload_too_large | 413 | The body exceeds 100 KB. |
| rate_limited | 429 | Too many requests — see Retry-After. |
| quota_exceeded | 429 | A daily or monthly quota of the API key's account is used up. X-Quota-Reset (and Retry-After) say when it starts over; retrying earlier cannot succeed. |
| internal_error | 500 | Unexpected server error. |
| scan_unreachable | 502 | The domain refused or dropped the connection on port 443. |
| scan_tls_error | 502 | The TLS handshake failed or presented no usable certificate. |
| service_unavailable | 503 | API keys cannot be verified right now (the key store is unreachable); retry shortly. |
| webhooks_unavailable | 503 | Webhooks are switched off on this server: it has no signing keys configured. |
| scan_timeout | 504 | The scan did not finish in time. |
| timeout | 504 | The operation did not finish within its time budget. |
Explorar
- Referencia de la APITodas las operaciones con sus campos, ejemplos en curl, JavaScript y Python, y sus códigos de error.
- Códigos de errorLos 25 códigos: estado HTTP, cuándo se produce, qué hacer y si hay que reintentar.
- Registro de cambiosLos cambios de la v1 hasta ahora y lo que cambiará cuando lleguen las claves de API.
- Servidor MCPDa a Claude, Cursor o VS Code las herramientas de ecdsa.com con una sola línea, sin necesidad de clave.
- SDKPróximamente, SDK oficiales para 8 lenguajes
Registro de cambios
Última versión: v1.1.0, 22 de octubre de 2026. La versión de la API forma parte de la ruta; los cambios incompatibles se publicarían como /api/v2: las respuestas de la v1 pueden ganar campos, pero no los perderán ni los cambiarán.