Integra Sygnet en tus pipelines y scripts Integrate Sygnet into your pipelines and scripts
Incluye tu clave API en la cabecera Authorization de cada petición:
Include your API key in the Authorization header of every request:
Authorization: Bearer apikey_<tu_claveyour_key>
Las claves empiezan siempre con apikey_ seguido de 64 caracteres hexadecimales.
Crea y gestiona tus claves desde el Dashboard → Claves API.
Keys always start with apikey_ followed by 64 hexadecimal characters.
Create and manage your keys from Dashboard → API Keys.
Los límites se aplican por IP. Cuando se supera, el servidor responde con 429 Too Many Requests
y la cabecera Retry-After: 3600.
Limits are applied per IP. When exceeded, the server responds with 429 Too Many Requests
and the Retry-After: 3600 header.
| OperaciónOperation | LímiteLimit |
|---|---|
| Emitir certificadoIssue certificate | 20 / horahour |
| Verificar / descargar badge / descargar PDF Verify / download badge / download PDF | 60 / horahour |
| Votar un certificadoVote on a certificate | 30 / horahour |
La generación de PDF es la operación más costosa en el servidor. Úsala solo cuando el usuario necesite el documento, no en cada emisión. PDF generation is the most expensive operation on the server. Use it only when the user needs the document, not on every issuance.
/api/certificados
Registra un certificado SIA. Si el hash ya está activo, devuelve OK sin duplicar. Registers a SIA certificate. If the hash is already active, returns OK without duplicating.
Body JSON
{
"hash": "<SHA3-512 hex, 128 chars>", // obligatoriorequired
"algorithm": "SHA3-512", // SHA3-512 (defectodefault) | SHA256
"sia_level": 1, // 1-5 (1=100% humanohuman, 5=100% IAAI)
"description": "Informe Q2 2026Report Q2 2026", // opcional, máx 500 charsoptional, max 500 chars
"file_size": 204800, // tamaño en bytessize in bytes
"expires_at": 1782000000 // timestamp Unix UTC de caducidadUnix UTC expiry timestamp
}
Respuesta (siempre HTTP 200)Response (always HTTP 200)
{"ok": true, "hash": "<hash>", "new": true}
// si el hash ya estaba activoif the hash was already active:
{"ok": true, "hash": "<hash>", "new": false, "own": true}
El hash SHA3-512 debe calcularse en el cliente antes de llamar a la API. La API nunca recibe el archivo, solo el hash. The SHA3-512 hash must be computed on the client before calling the API. The API never receives the file, only the hash.
/api/certificados/{hash}
Verifica un certificado. Público — no requiere autenticación. Verifies a certificate. Public — no authentication required.
RespuestaResponse
{
"ok": true,
"certificate": {
"file_hash": "abc123...",
"status": "active", // active | expired | revoked | renewed
"sia_level": 1,
"description": "Informe Q2Report Q2",
"uploaded_at": "2026-06-06T10:00:00",
"caduca_at": "2027-06-06T10:00:00",
"verification_count": 12,
"owner": "u-a3f9b2c1d4e5", // pseudónimo GDPRGDPR pseudonym
"votes": {
"total": 5,
"by_type": {"endorse": 4, "dissent": 1, "dispute": 0},
"user_vote": null
}
}
}
/api/certificados/{hash}/badge
Devuelve un badge SVG 220×26px coloreado por nivel SIA. Embebible como <img> en cualquier web.
Returns a 220×26px SVG badge coloured by SIA level. Embeddable as <img> in any website.
<img src="https://mysygnet.com/api/certificados/abc123.../badge"
alt="Sygnet certificadoSygnet certificate">
/api/certificados/{hash}/pdf
Descarga el certificado en PDF A4 formal. Público, sin autenticación. Downloads the certificate as a formal A4 PDF. Public, no authentication required.
/api/dashboard
Devuelve tus certificados ordenados por fecha descendente (los 50 más recientes). Returns your certificates ordered by descending date (the 50 most recent).
RespuestaResponse
{
"ok": true,
"total": 3,
"certs": [
{
"file_hash": "abc123...",
"status": "active",
"sia_level": 1,
"description": "Informe Q2Report Q2",
"uploaded_at": "2026-06-06T10:00:00",
"caduca_at": "2027-06-06T10:00:00",
"verification_count": 12
}
]
}
¿Nuevo en webhooks? Consulta la Guía de Webhooks para una explicación paso a paso con ejemplos de servidor completos. New to webhooks? Check the Webhooks Guide for a step-by-step explanation with full server examples.
Configura una URL en tu servidor. Cada vez que emitas un certificado, Sygnet enviará un POST
con los datos del certificado y una firma HMAC-SHA256 para que puedas verificar su autenticidad.
Set up a URL on your server. Every time you issue a certificate, Sygnet will send a POST
with the certificate data and an HMAC-SHA256 signature so you can verify its authenticity.
/api/user/webhooks
Lista tus webhooks activos e inactivos. Lists your active and inactive webhooks.
/api/user/webhooks
Crea un webhook. Máximo 5 por usuario. El secret se muestra una sola vez. Creates a webhook. Maximum 5 per user. The secret is shown only once.
{"name": "pipeline-informesreport-pipeline", "url": "https://mi-servidormy-server.com/webhook"}
Respuesta:Response:
{"id": 1, "name": "...", "url": "...", "secret": "abc123..."}
/api/user/webhooks/{id}
Activa o pausa un webhook. Activates or pauses a webhook.
{"active": false} // pausa el webhookpauses the webhook
/api/user/webhooks/{id}
Elimina un webhook permanentemente. Deletes a webhook permanently.
{
"event": "cert.created",
"hash": "abc123...",
"sia_level": 1,
"description": "Informe Q2 2026Report Q2 2026",
"caduca_at": "2027-06-06T10:00:00",
"issued_at": "2026-06-06T10:00:00Z",
"published_url": null,
"content_type": null
}
Cada llamada incluye la cabecera X-Sygnet-Signature: sha256=<hmac>.
Verifica siempre antes de procesar:
Every call includes the X-Sygnet-Signature: sha256=<hmac> header.
Always verify before processing:
# Python import hmac, hashlib def verificarverify(body: bytes, header_sig: str, secret: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, header_sig)
// Node.js
const crypto = require('crypto');
function verificarverify(body, headerSig, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(headerSig)
);
}
compare_digest / timingSafeEqual).
Una comparación directa con == es vulnerable a timing attacks.
Always use constant-time comparison (compare_digest / timingSafeEqual).
A direct comparison using == is vulnerable to timing attacks.
| CódigoCode | CausaCause | SoluciónSolution |
|---|---|---|
| 401 | Clave inválida o expirada Invalid or expired key | Genera una nueva clave en el Dashboard Generate a new key in the Dashboard |
| 400 | Hash inválido (no es SHA3-512 de 128 chars) Invalid hash (not a 128-char SHA3-512) | Verifica que calculas SHA3-512 y lo conviertes a hex Verify that you compute SHA3-512 and convert it to hex |
| 400 | sia_level fuera de rango sia_level out of range | Debe ser un entero entre 1 y 5 Must be an integer between 1 and 5 |
| 404 | Certificado no encontrado Certificate not found | El hash no coincide con ningún cert activo The hash does not match any active cert |
| 429 | Rate limit superado Rate limit exceeded |
Espera el tiempo indicado en Retry-After
Wait for the time specified in Retry-After
|
| 500 | Error interno del servidor Internal server error | Inténtalo de nuevo. Si persiste, usa el buzón de sugerencias Try again. If it persists, please use the feedback box |
Certifica un informe PDF desde Python antes de enviarlo al cliente. El informe no sale hasta que el certificado SIA está emitido. Certify a PDF report from Python before sending it to the client. The report is not released until the SIA certificate is issued.
import hashlib, time, requests API_KEY = "apikey_tu_clave_aquiyour_key_here" BASE_URL = "https://mysygnet.com/api" HEADERS = {"Authorization": f"Bearer {API_KEY}"} def sha3_512(path: str) -> str: h = hashlib.sha3_512() with open(path, "rb") as f: for chunk in iter(lambda: f.read(65536), b""): h.update(chunk) return h.hexdigest() def certificarcertify(path: str, descripciondescription: str, sia: int = 1) -> str: file_hash = sha3_512(path) caducaexpiry = int(time.time()) + 365 * 86400 # 1 año1 year r = requests.post( f"{BASE_URL}/certificados", headers={**HEADERS, "Content-Type": "application/json"}, json={ "hash": file_hash, "sia_level": sia, "description": descripciondescription, "expires_at": caducaexpiry, } ) r.raise_for_status() return file_hash # UsoUsage: hash_cert = certificarcertify("informe_q2_2026report_q2_2026.pdf", "Informe Q2 2026Report Q2 2026", sia=1) print(f"CertificadoCertified: {hash_cert}") print(f"VerificarVerify: {BASE_URL}/certificados/{hash_cert}") print(f"PDF: {BASE_URL}/certificados/{hash_cert}/pdf") # Adjunta el PDF del certificado como "Anexo A: Registro SIA"Attach the certificate PDF as "Annex A: SIA Registration Certificate"
El Prestigio Sygnet es un índice público de 0 a 100 que mide la confianza de un creador en la red. Se calcula automáticamente cada 24 horas a partir de cuatro componentes. La fórmula es pública y auditable para que cualquiera pueda verificar su puntuación. Sygnet Prestige is a public index from 0 to 100 that measures a creator's trust across the network. It is automatically calculated every 24 hours based on four components. The formula is public and auditable so anyone can verify their score.
¿Por qué no veo mi Prestigio todavía? Why don't I see my Prestige yet?
prestige_cache.
You need at least one certificate. The calculation only includes users who have certified content. Without certificates, you won't appear in prestige_cache.
computed_at: null en la respuesta de la API.
Sign that it hasn't been calculated yet: computed_at: null in the API response.
// Puntuación finalFinal score
score = max(0, min(100, pt_antigüedadseniority + pt_actividadactivity + pt_avalesendorsements + pt_notasnotes))
| ComponenteComponent | Máx.Max | FórmulaFormula |
|---|---|---|
| AntigüedadSeniority | 20 | min(20, log₂(díasdays/30 + 1) × 6.67) |
| ActividadActivity | 25 | min(25, log₂(certs_90d + 1) × 8.33) |
| Avales ponderadosWeighted Endorsements | 55 | min(55, Σ(score_avaladorendorser_score/100 × decay) × 7.33) |
| Chorus | −8 c/ueach | −8 × notas_visiblesvisible_notes |
Decaimiento de avales por antigüedad Endorsement decay by age
< 30 díasdays → factor 1.0 (peso completofull weight)
30–90 díasdays → factor 0.8
90–180 díasdays → factor 0.6
> 180 díasdays → factor 0.4
Los avales de cuentas con prestige > 0 valen más. Un aval de prestige=50 cuenta como 0.5 × decay. Endorsements from accounts with prestige > 0 are worth more. An endorsement from prestige=50 counts as 0.5 × decay.
Las notas solo se hacen visibles (y penalizan −8 pts) cuando tanto fans como desconocidos del creador las votan útiles. Esto evita que lobbies coordinen ataques o defensas. Notes only become visible (and penalize −8 pts) when both fans and strangers to the creator vote them as helpful. This prevents lobbies from coordinating attacks or defenses.
visible → util_fanshelpful_fans ≥ 2 AND util_extrahelpful_extra ≥ 2
rejected → noutil_fans/total_fansunhelpful_fans/total_fans ≥ 0.6 OR noutil_extra/total_extraunhelpful_extra/total_extra ≥ 0.6
quarantine → pendiente de votos suficientespending sufficient votes
/api/profile/{pseudonym}/prestige
Devuelve el prestige público de cualquier creador. No requiere autenticación. Returns the public prestige of any creator. No authentication required.
{
"ok": true,
"score": 42,
"breakdown": {
"antiguedadseniority": 12,
"actividadactivity": 10,
"avalesendorsements": 20,
"notasnotes": 0
},
"computed_at": "2026-06-07T04:00:00"
}
/api/user/prestige
Tu propio prestige + notas recibidas (requiere autenticación). Your own prestige + received notes (requires authentication).
{
"ok": true,
"score": 42,
"breakdown": { "antiguedadseniority": 12, "actividadactivity": 10, "avalesendorsements": 20, "notasnotes": 0 },
"computed_at": "2026-06-07T04:00:00",
"notas_recibidas_visiblesreceived_notes_visible": [ { "note_id": 1, "cert_hash": "abc…", "reason": "SIA_INCORRECTOSIA_INCORRECT", "body": "…" } ],
"notas_recibidas_quarantinereceived_notes_quarantine": 2
}
/api/certificados/{hash}/endorse
Avala al autor de un certificado. Requiere autenticación y no avalar tus propios certs. Idempotente. Límite: 10/hora. Endorse the author of a certificate. Requires authentication and you cannot endorse your own certs. Idempotent. Limit: 10/hour.
{"ok": true, "already": false} // "already": true si ya lo habías avalado antes"already": true if you had already endorsed it
/api/certificados/{hash}/notes
Escribe una entrada Chorus. Requiere: cuenta ≥ 7 días, cert propio ≥ 30 días, Prestigio ≥ 5 pts (ver sección 9 para el detalle completo). Límite: 5/hora. Solo 1 entrada por usuario por certificado. Write a Chorus entry. Requires: account ≥ 7 days, own cert ≥ 30 days, Prestige ≥ 5 pts (see section 9 for full detail). Limit: 5/hour. Only 1 entry per user per certificate.
// Body
{"reason": "SIA_INCORRECTOSIA_INCORRECT", "body": "El nivel SIA indicado no corresponde al contenido…The indicated SIA level does not match the content…"}
// Razones válidasValid reasons: SIA_INCORRECTO | URL_ROTA | AUTORIA_DUDOSA
// RespuestaResponse
{"ok": true, "note_id": 42}
El sistema de notas permite a la comunidad añadir contexto a cualquier certificado. Las notas pasan por un algoritmo bridge antes de ser públicas. Si el propietario disputa una nota, se abre un proceso de arbitraje por voto ponderado (contenido público) o por mediación bilateral (contenido privado). The notes system lets the community add context to any certificate. Notes go through a bridge algorithm before becoming public. If the owner disputes a note, a weighted-vote arbitration (public content) or bilateral mediation (private content) is opened.
/api/certificados/{hash}/notes
Crea una entrada Chorus. Requiere: cuenta ≥ 7 días, cert propio ≥ 30 días, Prestigio ≥ 5 pts. Máx 1 entrada por usuario por cert. Creates a Chorus entry. Requires: account ≥ 7 days, own cert ≥ 30 days, Prestige ≥ 5 pts. Max 1 entry per user per cert.
{ "reason": "SIA_INCORRECTO" | "AUTORIA_DUDOSA", "body": "textotext (1-280 chars)" }
{"ok": true, "note_id": 42}
/api/certificados/{hash}/notes
Lista notas públicas (quarantine + visible). Con JWT incluye user_has_cert, is_own, can_rate, can_vote_dispute.
Lists public notes (quarantine + visible). With JWT includes user_has_cert, is_own, can_rate, can_vote_dispute.
/api/notes/{id}/rate
Valora una nota en cuarentena. Rate: 20/h. Desencadena el algoritmo bridge. Rates a note in quarantine. Rate: 20/h. Triggers the bridge algorithm.
{ "rating": "util" | "no_util" }
/api/notes/{id}/dispute_vote
Vota en una disputa activa. Requiere Prestigio ≥ 15 (o ≥ 5 si bootstrap_mode=true) + cuenta ≥ 30 días. Votación disponible 48 h después del inicio de la disputa. Votes in an active dispute. Requires Prestige ≥ 15 (or ≥ 5 if bootstrap_mode=true) + account ≥ 30 days. Voting available 48 h after dispute start.
{ "side": "mantener" | "rechazar" }
/api/notes/{id}/offer_mediation
Ofrecerse como mediador en disputas de contenido privado (sin URL publicada). Requiere Prestigio ≥ 30, idioma común con el propietario, sin endorsements cruzados con ninguna parte en 90 días. Volunteer as mediator in private content disputes (no published URL). Requires Prestige ≥ 30, shared language with owner, no cross-endorsements with any party in 90 days.
/api/notes/disputes
Lista todas las disputas activas. Público. Con JWT incluye user_is_creator, user_is_author, user_is_mediator, mediators (lista de candidatos, solo para las partes).
Lists all active disputes. Public. With JWT includes user_is_creator, user_is_author, user_is_mediator, mediators (candidate list, parties only).
/api/certificados/{hash}/report_url
Reporta el enlace publicado de un certificado como roto. El creador tiene 7 días para arreglarlo antes de que aparezca una nota automática. Rate: 5/h. Solo para certs con published_url. Reports the published link of a certificate as broken. The creator has 7 days to fix it before an automatic note appears. Rate: 5/h. Only for certs with published_url.
/api/user/notifications
Notificaciones del usuario autenticado (JWT). Paginado: ?offset=0&limit=20. Las no leídas aparecen primero.
Notifications for the authenticated user (JWT). Paginated: ?offset=0&limit=20. Unread items appear first.
GET /api/user/notifications/count → {"ok": true, "unread": 3}
POST /api/user/notifications/read
{ "ids": [1, 2] } // vacío = marcar todas// empty = mark all