Kehittäjille
API-dokumentaatio
Signeurin REST-API antaa sovelluksesi luoda allekirjoituspyyntöjä, seurata niiden tilaa ja noutaa lukittuja PDF-tiedostoja. Tämä dokumentaatio kuvaa tällä hetkellä toteutetut päätepisteet.
https://signeur.euAutentikointi
Kaikki API-kutsut vaativat Bearer-tokenin Authorization-otsikossa. Avainparametrit hashataan SHA-256:lla ja verrataan tallennettuun hashiin — plain-textiä ei tallenneta missään.
Esimerkki:
Authorization: Bearer sgn_live_xxx...Hanki API-key palvelun ylläpitäjältä. Avainformaatti on sgn_live_<random>.
Virhevastaukset
Kaikki virheet palautetaan JSON-muodossa kentillä error ja message. HTTP-tilakoodit noudattavat standardia.
{
"error": "invalid_signer_email",
"message": "Field 'signer_email' is missing or not a valid email."
}| Koodi | Merkitys |
|---|---|
400 | Bad request (validointi ei mene läpi) |
401 | Authorization-otsikko puuttuu tai Bearer-token virheellinen |
404 | Resurssia ei löytynyt tai se kuuluu toiselle organisaatiolle |
409 | Konflikti: pyyntö on jo allekirjoitettu / ei vielä allekirjoitettu |
410 | Resurssi on vanhentunut (linkki yli 30 päivää vanha) |
429 | Liian monta pyyntöä — odota Retry-After-otsikon ilmoittama aika |
500 | Palvelinvirhe (DB-, Storage- tai email-välitysvirhe) |
Rate-limit
Tällä hetkellä per-organisaatiotason rate-limittausta ei ole käytössä. Käytä API:a vastuullisesti — väärinkäyttö voi johtaa avaimen perumiseen. Volyymikohtaiset takarajat lisätään myöhemmin.
Idempotenssi
Kaikki POST-endpointit hyväksyvät vapaaehtoisen `Idempotency-Key`-headerin (mikä tahansa uniikki merkkijono, tyypillisesti UUID). Jos retryät saman avaimen kanssa, Signeur palauttaa alkuperäisen vastauksen sen sijaan että loisi duplikaatin. Avaimet ovat organisaatiokohtaisia ja säilyvät 24 tuntia.
POST /api/v1/signatures
Authorization: Bearer sgn_live_...
Idempotency-Key: 0d8a2c41-7e3f-4b9d-bc59-2c5fd8a91f4d
Content-Type: application/json
{ … }Jos lähetät saman avaimen eri body:lla, Signeur palauttaa 409 idempotency_key_conflict. Toistetut vastaukset sisältävät `Idempotent-Replayed: true`-headerin client-puolen tunnistamiseen.
Päätepisteet
Luo allekirjoituspyyntö
Luo uusi allekirjoituspyyntö (1–20 allekirjoittajaa), tallentaa PDF:n Storageen ja lähettää kutsu-emailit kaikille allekirjoittajille.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
title | string | kyllä | Allekirjoituspyynnön otsikko (näkyy kutsu-emailissa). |
message | string | ei | Valinnainen viesti, joka näytetään jokaiselle allekirjoittajalle. |
signers[] | array | kyllä | Lista 1–20 signer-objektista. Vähintään yksi vaaditaan. |
signers[].email | string | kyllä | Allekirjoittajan sähköpostiosoite. |
signers[].name | string | ei | Allekirjoittajan nimi (näkyy audit-sivulla). |
signers[].locale | string | ei | Per-signer email-kieli: 'en' | 'fi' | 'fr' | 'de'. Fallback ensin top-level locale:en, sitten 'en'. |
locale | string | ei | Default-locale niille signereille jotka eivät määritä omaa. Sallitut arvot: 'en' | 'fi' | 'fr' | 'de'. |
document.filename | string | kyllä | PDF:n alkuperäinen tiedostonimi. |
document.content_base64 | string | kyllä | PDF base64-koodattuna (max 10 MB dekoodattuna). |
metadata | object | ei | Vapaamuotoinen avain-arvopari-tietue, joka tallennetaan sellaisenaan. |
Yhteensopivuus: vanhempi single-signer-body { "signer_email", "signer_name" } toimii edelleen ja muunnetaan sisäisesti yhden alkion signers-arrayksi. Uudet integraatiot kannattaa kuitenkin tehdä signers[]-formaatilla.
Pyynnön body
curl -X POST https://signeur.eu/api/v1/signatures \
-H "Authorization: Bearer sgn_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Order Agreement #1234",
"message": "Please review and sign.",
"locale": "en",
"signers": [
{ "email": "buyer@example.com", "name": "Anna Buyer" },
{ "email": "seller@example.com", "name": "Bob Seller", "locale": "fi" }
],
"document": {
"filename": "contract.pdf",
"content_base64": "JVBERi0xLjQK..."
},
"metadata": { "deal_id": "D-42" }
}'Vastaus
{
"id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"status": "sent",
"expires_at": "2026-06-13T10:51:51.813+00:00",
"signers": [
{
"id": "9c0aa5ec-…",
"email": "buyer@example.com",
"name": "Anna Buyer",
"access_token": "29ErQSUr8Ov…",
"sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
"email_sent": true,
"email_error": null,
"locale": "en"
},
{
"id": "f12d8b3c-…",
"email": "seller@example.com",
"name": "Bob Seller",
"access_token": "kpqDAuVy9-…",
"sign_url": "https://signeur.eu/sign/kpqDAuVy9-…",
"email_sent": true,
"email_error": null,
"locale": "fi"
}
]
}Hae allekirjoituspyynnön tila
Palauttaa pyynnön nykyisen tilan, koko signers-arrayn ja audit-trailin. Käytetään statuksen seurantaan.
Pyynnön body
curl https://signeur.eu/api/v1/signatures/<id> \
-H "Authorization: Bearer sgn_live_..."Vastaus
{
"id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"status": "signed",
"title": "Order Agreement #1234",
"created_at": "2026-05-14T10:51:51.813Z",
"sent_at": "2026-05-14T10:51:52.012Z",
"signed_at": "2026-05-14T10:52:24.374Z",
"cancelled_at": null,
"expires_at": "2026-06-13T10:51:51.813Z",
"is_expired": false,
"signers": [
{
"id": "9c0aa5ec-…",
"email": "buyer@example.com",
"name": "Anna Buyer",
"access_token": "29ErQSUr8Ov…",
"sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
"status": "signed",
"sent_at": "2026-05-14T10:51:52.012Z",
"opened_at": "2026-05-14T10:52:00.481Z",
"signed_at": "2026-05-14T10:52:24.374Z",
"declined_at": null,
"decline_reason": null,
"locale": "en"
}
],
"document_hash": "e5132c2fe36dfa219ec600b009d16ef38d20bf0849f7b01ba5ca6e22fec63b56",
"audit_trail": { "events": [ … ] },
"metadata": { "deal_id": "D-42" }
}Lataa allekirjoitettu PDF
Palauttaa lukitun PDF:n binaryna. Palauttaa 409, jos pyyntöä ei ole vielä allekirjoitettu.
Pyynnön body
curl https://signeur.eu/api/v1/signatures/<id>/document \
-H "Authorization: Bearer sgn_live_..." \
-o signed.pdfContent-Type: application/pdf
Listaa allekirjoituspyynnöt
Palauttaa organisaation pyyntöjen paginoidun listan suodattimilla.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
status | query | ei | Suodata statuksella: pending | sent | opened | signed | cancelled | declined | expired | awaiting_stamp | stamp_failed. |
created_from | query | ei | Palauta vain pyynnöt, joiden created_at on tämä ISO-8601 aikaleima tai sen jälkeen. |
created_to | query | ei | Palauta vain pyynnöt, joiden created_at on ennen tätä ISO-8601 aikaleimaa. |
limit | query | ei | Sivun koko, 1–100. Oletus 25. |
cursor | query | ei | Opaakki cursor, joka saatiin edellisen vastauksen next_cursor-arvosta. Älä rakenna itse. |
Pyynnön body
curl "https://signeur.eu/api/v1/signatures?status=sent&limit=10" \
-H "Authorization: Bearer sgn_live_..."Vastaus
{
"data": [
{
"id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"status": "sent",
"title": "Order Agreement #1234",
"signer_count": 2,
"created_at": "2026-05-14T10:51:51.813Z",
"sent_at": "2026-05-14T10:51:52.012Z",
"signed_at": null,
"cancelled_at": null,
"expires_at": "2026-06-13T10:51:51.813Z",
"is_expired": false
}
],
"has_more": true,
"next_cursor": "eyJjIjoiMjAyNi0wNS0xNFQxMDo1MTo1MS44MTNaIiwiaSI6IjZkYzE4OTExLi4uIn0"
}Peruuta allekirjoituspyyntö
Peruuttaa avoimen pyynnön, invalidoi kaikki vielä aktiiviset signer-linkit ja lähettää signature_request.cancelled-webhookin.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
reason | string | ei | Valinnainen peruste, tallennetaan audit-trailiin (max 500 merkkiä). |
Pyynnön body
curl -X POST https://signeur.eu/api/v1/signatures/<id>/cancel \
-H "Authorization: Bearer sgn_live_..." \
-H "Content-Type: application/json" \
-d '{ "reason": "Sent to wrong recipient" }'Vastaus
{
"id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"status": "cancelled",
"cancelled_at": "2026-05-17T08:14:02.913Z"
}Vaikutus: status muuttuu 'cancelled'-tilaan, kaikki allekirjoittamattomat signer-linkit invalidoidaan ja signature_request.cancelled-webhook lähetetään. Alkuperäinen PDF säilyy DB:ssä, mutta sitä ei voi enää ladata /document-reitin kautta.
Listaa pyynnön allekirjoittajat
Palauttaa kaikki signer-rivit yhden pyynnön sisällä per-signer-tiloineen, aikaleimineen ja audit-traileineen. Käytetään multi-signer-edistymisen näyttöön.
Pyynnön body
curl "https://signeur.eu/api/v1/signatures/<id>/signers" \
-H "Authorization: Bearer sgn_live_..."Vastaus
{
"data": [
{
"id": "9c0aa5ec-…",
"email": "buyer@example.com",
"name": "Anna Buyer",
"name_as_invited": "Anna Buyer",
"name_as_signed": "Anna H. Buyer",
"access_token": "29ErQSUr8Ov…",
"sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
"status": "signed",
"position": 0,
"sent_at": "2026-05-14T10:51:52.012Z",
"opened_at": "2026-05-14T10:52:00.481Z",
"signed_at": "2026-05-14T10:52:24.374Z",
"declined_at": null,
"decline_reason": null,
"invalidated_at": null,
"ip_address": "87.92.91.57",
"user_agent": "Mozilla/5.0 (Macintosh; …) Safari/605.1.15",
"locale": "en",
"representing_as_invited": null,
"representing_as_signed": null,
"representing_role": null,
"representing_entity_id": null,
"audit_trail": { "events": [ … ] }
},
{
"id": "f12d8b3c-…",
"email": "seller@example.com",
"status": "pending",
"position": 1,
"...": "..."
}
]
}Lähetä kutsu uudelleen
Lähettää kutsu-emailin yhdelle signerille uudestaan tuoreella access-koodilla. Vanha koodi lakkaa toimimasta heti.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
locale | string | ei | Valinnainen. Korvaa signerin email-localen tällä lähetyksellä ja tallenna muutos signer-riville. Sallitut: 'en' | 'fi' | 'fr' | 'de'. |
Pyynnön body
curl -X POST https://signeur.eu/api/v1/signatures/<id>/signers/<signer_id>/resend \
-H "Authorization: Bearer sgn_live_..." \
-H "Content-Type: application/json" \
-d '{ "locale": "fi" }'Vastaus
{
"ok": true,
"signer_id": "9c0aa5ec-…",
"email_sent": true,
"email_error": null,
"access_code_rotated_at": "2026-05-17T10:14:33.872Z"
}Vaikutus: uusi 6-numeroinen access-koodi generoidaan, tallennetaan bcrypt-hashattuna ja lähetetään signerille emailissa. Aiemmin lähetetty koodi ei enää tunnista access-code-portilla. Yritys-laskuri ja mahdolliset väliaikaiset lukot resetoidaan.
Lataa audit-trail-PDF
Palauttaa erillisen PDF:n joka sisältää koko auditkirjauksen: pyynnön metatiedot, signereiden tiedot IP-osoitteineen ja user-agent-tietoineen, kronologisen event-aikajanan sekä PAdES-allekirjoituksen tiedot kun pyyntö on sinetöity. Tämä PDF on informatiivinen eikä ole kryptografisesti allekirjoitettu — sinetöity itse asiakirja on juridinen todiste.
Pyynnön body
curl https://signeur.eu/api/v1/signatures/<id>/audit-trail.pdf \
-H "Authorization: Bearer sgn_live_..." \
-o audit-trail.pdfContent-Type: application/pdf · PDF generoidaan pyynnön nykyisestä tilasta ja audit-trailista. Saatavilla riippumatta pyynnön statuksesta.
Listaa webhook-endpointit
Palauttaa organisaation kaikki webhook-endpointit. Secret-arvot eivät tule listauksessa — ne näytetään vain luonnin yhteydessä yhden kerran.
Pyynnön body
curl https://signeur.eu/api/v1/webhook-endpoints \
-H "Authorization: Bearer sgn_live_..."Vastaus
{
"data": [
{
"id": "ep_a1b2c3d4-…",
"url": "https://example.com/hooks/signeur",
"event_types": ["signature_request.completed", "signer.signed"],
"description": "Production sync",
"disabled_at": null,
"created_at": "2026-05-17T10:00:00.000Z",
"updated_at": "2026-05-17T10:00:00.000Z"
}
]
}Luo webhook-endpoint
Rekisteröi uuden URL:n vastaanottamaan webhook-eventejä. Vastaus sisältää tuoreen `secret`-arvon joka näytetään vain tämän kerran ja jota käytetään HMAC-allekirjoitusten verifiointiin saapuvissa webhookeissa.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
url | string | kyllä | Toimituskohteen URL (pakko olla https:// tuotannossa, http://localhost on sallittu kehityksessä). |
event_types | string[] | ei | Lista event-tyypeistä joita vastaanotetaan. Tyhjä lista (tai pois jätetty) = vastaanotetaan kaikki eventit. |
description | string | ei | Valinnainen lyhyt seliteteksti endpointille (max 200 merkkiä). |
Pyynnön body
curl -X POST https://signeur.eu/api/v1/webhook-endpoints \
-H "Authorization: Bearer sgn_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/signeur",
"event_types": ["signature_request.completed", "signer.signed"],
"description": "Production sync"
}'Vastaus
{
"id": "ep_a1b2c3d4-…",
"url": "https://example.com/hooks/signeur",
"secret": "whsec_7f3a9c…",
"event_types": ["signature_request.completed", "signer.signed"],
"description": "Production sync",
"disabled_at": null,
"created_at": "2026-05-17T10:00:00.000Z",
"updated_at": "2026-05-17T10:00:00.000Z"
}Tärkeää: secret näkyy VAIN tässä vastauksessa. Signeur ei säilytä plain-text-versiota. Jos hukkaat sen, poista tämä endpoint ja luo uusi.
Päivitä webhook-endpoint
Päivittää endpointin url, event_types, description tai disabled-tila. Kaikki body-kentät ovat valinnaisia — vain annetut muuttuvat.
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
url | string | ei | Toimituskohteen URL (pakko olla https:// tuotannossa, http://localhost on sallittu kehityksessä). |
event_types | string[] | ei | Lista event-tyypeistä joita vastaanotetaan. Tyhjä lista (tai pois jätetty) = vastaanotetaan kaikki eventit. |
description | string | ei | Valinnainen lyhyt seliteteksti endpointille (max 200 merkkiä). |
disabled | boolean | ei | true = pysäytä toimitus poistamatta endpointia, false = jatka. |
Poista webhook-endpoint
Poistaa endpointin pysyvästi. Eventien toimitus loppuu välittömästi. Secret on palautumaton poiston jälkeen.
curl -X DELETE https://signeur.eu/api/v1/webhook-endpoints/<id> \
-H "Authorization: Bearer sgn_live_..."Webhookit
Signeur lähettää tapahtumaviestit (events) reaaliaikaisesti yhteen tai useampaan organisaatiolle määritettyyn URL-osoitteeseen, kun allekirjoituspyynnön tila muuttuu. Jokainen event allekirjoitetaan HMAC-SHA256:lla ja toimitetaan rinnakkain kaikkiin sopiviin endpointteihin. Tämä on tehokkaampi vaihtoehto kuin GET-endpointin pollaaminen.
Tuetut tapahtumat
signature_request.created | Uusi allekirjoituspyyntö luotu. Fires kerran per pyyntö, sisältää koko signers-listan. |
signature_request.sent | Kutsu-email-batch yritetty kaikille signereille. Sisältää per-signer email_sent-statuksen. |
signature_request.opened | Allekirjoittaja avasi linkin ensimmäistä kertaa. Fires kerran per pyyntö kun ensimmäinen signer avaa sen. |
signer.signed | Yksittäinen signer suoritti OTP-vahvistuksen ja allekirjoitti. Fires N kertaa N-signerin pyynnössä. |
signature_request.completed | Kaikki signereistä ovat allekirjoittaneet ja dokumentti on sinetöity. Sisältää document_hashin ja download_url:n. |
signature_request.signed | Deprecated — sama hetki kuin signature_request.completed. Uusissa integraatioissa käytä signature_request.completed. |
signature_request.declined | Joku signereistä kieltäytyi; pyyntö siirtyi 'declined'-tilaan ja jäljellä olevat signerit invalidoitiin. |
signature_request.cancelled | Pyyntö peruttiin dashboardin tai POST /signatures/{id}/cancel-endpointin kautta. |
signature_request.expired | Pyyntö saavutti expires_at-ajan ilman että kaikki allekirjoittajat ehtivät. Lähetetään kerran per pyyntö kun expire-cron siirtää statuksen 'expired'-tilaan (max ~24 h viive Vercel Hobby -tilauksella). |
Payload-muoto
// signer.signed — fires once per signer that finishes signing
{
"id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "signer.signed",
"created_at": "2026-05-14T10:52:24.374Z",
"data": {
"signature_request_id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"signer_id": "9c0aa5ec-…",
"signer_email": "buyer@example.com",
"signer_name": "Anna Buyer",
"signed_at": "2026-05-14T10:52:24.374Z",
"remaining_pending_signers": 1
}
}
// signature_request.completed — fires once when all signers are done
// and the PDF is sealed. signature_request.signed is a deprecated alias
// that fires at the same moment with the same payload.
{
"id": "evt_b2c3d4e5-f6a7-8901-bcde-f23456789012",
"type": "signature_request.completed",
"created_at": "2026-05-14T10:55:11.812Z",
"data": {
"signature_request_id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
"status": "signed",
"signed_at": "2026-05-14T10:55:11.812Z",
"document_hash": "e5132c2fe36dfa…",
"download_url": "https://signeur.eu/api/v1/signatures/6dc18911-…/document"
}
}Allekirjoituksen verifiointi
Jokaiseen webhookiin liitetään HMAC-SHA256-allekirjoitus headerissa X-Signeur-Signature. Verifioi se varmistaaksesi että pyyntö tuli aidosti Signeurilta.
Header-muoto:
X-Signeur-Signature: t=1747212744,v1=abc123def456...Allekirjoitettu data:
<timestamp>.<raw json body>Esimerkki verifioinnista (Node.js):
import { createHmac } from "crypto";
// Verify webhook signature
const sig = req.headers["x-signeur-signature"];
const [t, v1] = sig.split(",").map(s => s.split("=")[1]);
const expected = createHmac("sha256", YOUR_WEBHOOK_SECRET)
.update(`${t}.${rawBody}`).digest("hex");
if (v1 !== expected) throw new Error("Invalid signature");Konfigurointi
Endpointteja voi konfiguroida kahdella tavalla: (a) Dashboard → Webhookit tarjoaa UI:n endpointtien lisäämiseen, muokkaamiseen, pausettamiseen ja poistamiseen sekä event-tyyppien valintaan per endpoint. (b) REST API /api/v1/webhook-endpoints sallii ohjelmallisen hallinnan. Jokainen endpoint saa oman HMAC-secretin joka näytetään vain luonnin yhteydessä — tallenna se turvallisesti. Legacy yhden URL:n webhook organisaation tasolla toimii edelleen fallbackina, jos uudessa taulussa ei ole rivejä.
Toimitus
Kun event ampuu, Signeur etsii kaikki aktiiviset endpointit jotka tilaavat event-tyyppiä ja toimittaa payloadin rinnakkain (5 sekunnin timeout per endpoint). Jokainen yritys tallennetaan erikseen signature_requestin audit-trailiin endpoint-id:n, HTTP-statuksen ja mahdollisen virheen kanssa. Retry-queue on roadmapilla.
Tulossa pian
Seuraavat ominaisuudet ovat suunnitteilla:
- → Automaattinen vanhentumistarkkailu joka ampuu signature_request.expired-eventin (nyt status pysyy 'sent'/'opened' vaikka expires_at olisi mennyt)
- → Webhook retry-queue — nyt jokainen toimitus on yksi yritys; epäonnistuneet eventit eivät yritä uudelleen
- → Idempotency-Key-tuki cancel- ja resend-endpointeille (nyt vain POST /signatures)
- → Webhook delivery -historianäkymä dashboardiin