Tämä sivu on käännetty tekoälyllä alkuperäisestä englanninkielisestä versiosta. Englanninkielinen versio on määräävä.

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.

Pohja-URLhttps://signeur.eu
OpenAPI 3.1 -spec

Autentikointi

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."
}
KoodiMerkitys
400Bad request (validointi ei mene läpi)
401Authorization-otsikko puuttuu tai Bearer-token virheellinen
404Resurssia ei löytynyt tai se kuuluu toiselle organisaatiolle
409Konflikti: pyyntö on jo allekirjoitettu / ei vielä allekirjoitettu
410Resurssi on vanhentunut (linkki yli 30 päivää vanha)
429Liian monta pyyntöä — odota Retry-After-otsikon ilmoittama aika
500Palvelinvirhe (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

POST/api/v1/signatures

Luo allekirjoituspyyntö

Luo uusi allekirjoituspyyntö (1–20 allekirjoittajaa), tallentaa PDF:n Storageen ja lähettää kutsu-emailit kaikille allekirjoittajille.

KenttäTyyppiPakollinenKuvaus
titlestringkylläAllekirjoituspyynnön otsikko (näkyy kutsu-emailissa).
messagestringeiValinnainen viesti, joka näytetään jokaiselle allekirjoittajalle.
signers[]arraykylläLista 1–20 signer-objektista. Vähintään yksi vaaditaan.
signers[].emailstringkylläAllekirjoittajan sähköpostiosoite.
signers[].namestringeiAllekirjoittajan nimi (näkyy audit-sivulla).
signers[].localestringeiPer-signer email-kieli: 'en' | 'fi' | 'fr' | 'de'. Fallback ensin top-level locale:en, sitten 'en'.
localestringeiDefault-locale niille signereille jotka eivät määritä omaa. Sallitut arvot: 'en' | 'fi' | 'fr' | 'de'.
document.filenamestringkylläPDF:n alkuperäinen tiedostonimi.
document.content_base64stringkylläPDF base64-koodattuna (max 10 MB dekoodattuna).
metadataobjecteiVapaamuotoinen 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"
    }
  ]
}
GET/api/v1/signatures/{id}

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" }
}
GET/api/v1/signatures/{id}/document

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.pdf

Content-Type: application/pdf

GET/api/v1/signatures

Listaa allekirjoituspyynnöt

Palauttaa organisaation pyyntöjen paginoidun listan suodattimilla.

KenttäTyyppiPakollinenKuvaus
statusqueryeiSuodata statuksella: pending | sent | opened | signed | cancelled | declined | expired | awaiting_stamp | stamp_failed.
created_fromqueryeiPalauta vain pyynnöt, joiden created_at on tämä ISO-8601 aikaleima tai sen jälkeen.
created_toqueryeiPalauta vain pyynnöt, joiden created_at on ennen tätä ISO-8601 aikaleimaa.
limitqueryeiSivun koko, 1–100. Oletus 25.
cursorqueryeiOpaakki 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"
}
POST/api/v1/signatures/{id}/cancel

Peruuta allekirjoituspyyntö

Peruuttaa avoimen pyynnön, invalidoi kaikki vielä aktiiviset signer-linkit ja lähettää signature_request.cancelled-webhookin.

KenttäTyyppiPakollinenKuvaus
reasonstringeiValinnainen 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.

GET/api/v1/signatures/{id}/signers

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,
      "...": "..."
    }
  ]
}
POST/api/v1/signatures/{id}/signers/{signer_id}/resend

Lähetä kutsu uudelleen

Lähettää kutsu-emailin yhdelle signerille uudestaan tuoreella access-koodilla. Vanha koodi lakkaa toimimasta heti.

KenttäTyyppiPakollinenKuvaus
localestringeiValinnainen. 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.

GET/api/v1/signatures/{id}/audit-trail.pdf

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.pdf

Content-Type: application/pdf · PDF generoidaan pyynnön nykyisestä tilasta ja audit-trailista. Saatavilla riippumatta pyynnön statuksesta.

GET/api/v1/webhook-endpoints

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"
    }
  ]
}
POST/api/v1/webhook-endpoints

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äTyyppiPakollinenKuvaus
urlstringkylläToimituskohteen URL (pakko olla https:// tuotannossa, http://localhost on sallittu kehityksessä).
event_typesstring[]eiLista event-tyypeistä joita vastaanotetaan. Tyhjä lista (tai pois jätetty) = vastaanotetaan kaikki eventit.
descriptionstringeiValinnainen 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.

PATCH/api/v1/webhook-endpoints/{id}

Päivitä webhook-endpoint

Päivittää endpointin url, event_types, description tai disabled-tila. Kaikki body-kentät ovat valinnaisia — vain annetut muuttuvat.

KenttäTyyppiPakollinenKuvaus
urlstringeiToimituskohteen URL (pakko olla https:// tuotannossa, http://localhost on sallittu kehityksessä).
event_typesstring[]eiLista event-tyypeistä joita vastaanotetaan. Tyhjä lista (tai pois jätetty) = vastaanotetaan kaikki eventit.
descriptionstringeiValinnainen lyhyt seliteteksti endpointille (max 200 merkkiä).
disabledbooleaneitrue = pysäytä toimitus poistamatta endpointia, false = jatka.
DELETE/api/v1/webhook-endpoints/{id}

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.createdUusi allekirjoituspyyntö luotu. Fires kerran per pyyntö, sisältää koko signers-listan.
signature_request.sentKutsu-email-batch yritetty kaikille signereille. Sisältää per-signer email_sent-statuksen.
signature_request.openedAllekirjoittaja avasi linkin ensimmäistä kertaa. Fires kerran per pyyntö kun ensimmäinen signer avaa sen.
signer.signedYksittäinen signer suoritti OTP-vahvistuksen ja allekirjoitti. Fires N kertaa N-signerin pyynnössä.
signature_request.completedKaikki signereistä ovat allekirjoittaneet ja dokumentti on sinetöity. Sisältää document_hashin ja download_url:n.
signature_request.signedDeprecated — sama hetki kuin signature_request.completed. Uusissa integraatioissa käytä signature_request.completed.
signature_request.declinedJoku signereistä kieltäytyi; pyyntö siirtyi 'declined'-tilaan ja jäljellä olevat signerit invalidoitiin.
signature_request.cancelledPyyntö peruttiin dashboardin tai POST /signatures/{id}/cancel-endpointin kautta.
signature_request.expiredPyyntö 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