API reference for AI agents

Tidvis Sign API — endpoints, scopes and schemas

Machine-readable, SSR-rendered reference for the Tidvis Sign REST API v1 and MCP server. Every endpoint, scope, request body and response shape rendered without JavaScript so AI agents, MCP clients and LLM crawlers can index it. Interactive human-facing docs live at /utvecklare/api/spec.

Base URL: https://tidvis.se/api/public/v1 — MCP endpoint: https://tidvis.se/api/mcp — Discovery: /.well-known/mcp.json

Pricing: 3 free signings, then Sign Pro 199 SEK/seat/month or pay-per-agreement 19 SEK. Agreement generator module 99 SEK/user/month + 3 SEK/generation via MCP.

OAuth

Token-utgivning

POST /oauth/access-token

Issue access token (client-credentials)

OAuth

Public (no auth).

Returnerar en bearer-token (TTL 1h). Rate-limited per IP (10/min) och per client_id (30/min).

Request body

  • client_id: string required
  • client_secret: string required
Example
{
  "client_id": "tvs_live_8f3a9c2b1d",
  "client_secret": "sk_live_7e1d4f6a9c2b3e5f8a0c1b2d4e6f7a8b"
}

Responses

  • 200 — OK
    • access_token: string
    • token_type: string
    • expires_in: integer
    • scope: string
  • 400 — Invalid request
  • 401 — Invalid client credentials
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /oauth/access-token

Revoke current access token

OAuth

Requires bearer token.

Responses

  • 204 — Revoked
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Agreements

Avtal, deltagare, livscykel

GET /agreements

List agreements

Agreements

Scopes: agreements:read

List agreements owned by the calling client. Default returnerar bara aktuella versioner (`group=latest`); använd `group=all` för att inkludera superseded versioner (t.ex. tidigare avtal som ersatts av en ny HubSpot-omsändning). Stödjer filtrering på `external_id`, `external_source` och `status`.

Responses

  • 200 — OK
    • agreements: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements

Create draft agreement

Agreements

Scopes: agreements:create

Request body

  • title: string required
  • message: string
  • expires_at: string (date-time)
  • callback_url: string (uri)
  • metadata: object
  • bankid_required: boolean
  • bankid_identify_required: boolean
  • external_id: string
  • external_source: string
  • external_url: string (uri)
  • sender: object — Avsändare — autosigneras vid send (samma beteende som UI-flödet). Läggs till som is_sender=true och skickar inget signeringsmail.
  • auto_reminders: object — Automatic reminder settings (defaults: enabled=true, interval_days=3, max_reminders=3). Reminders run daily via cron; requires the account-level auto-reminder toggle to also be enabled.
Example
{
  "title": "Konsultavtal Q3 2026 – Acme AB",
  "message": "Hej! Vänligen signera bifogat konsultavtal senast 30 juni.",
  "expires_at": "2026-06-30T23:59:59Z",
  "bankid_required": true,
  "external_id": "deal_38291",
  "external_source": "hubspot",
  "sender": {
    "name": "Anna Andersson",
    "email": "anna@tidvis.se"
  },
  "metadata": {
    "deal_owner": "anna@tidvis.se",
    "region": "SE"
  },
  "auto_reminders": {
    "enabled": true,
    "interval_days": 3,
    "max_reminders": 3
  }
}

Responses

  • 201 — Created
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Enterprise-planen krävs
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}

Get agreement

Agreements

Scopes: agreements:read

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /agreements/{id}

Update agreement metadata and reminder settings

Agreements

Scopes: agreements:create

Patch a live or draft agreement. `title`, `message`, `metadata`, `callback_url`, `external_url`, `sender` och `auto_reminders.*` can be updated. `sender` kan bara ändras i status `draft` (autosigneras vid send). Rejected with 409 for terminal statuses (completed, cancelled, declined, deleted, expired).

Request body

  • title: string
  • message: string
  • callback_url: string (uri)
  • external_url: string (uri)
  • metadata: object
  • sender: object — Sätter/uppdaterar avsändaren som autosigneras vid send. Skicka null för att ta bort. Endast i status draft.
  • auto_reminders: object
Example
{
  "message": "Uppdaterat: signera senast 30 juni!",
  "auto_reminders": {
    "enabled": true,
    "interval_days": 2,
    "max_reminders": 5
  }
}

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /agreements/{id}

Delete draft agreement

Agreements

Scopes: agreements:create

Responses

  • 204 — Deleted
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}/versions

Get version chain

Agreements

Scopes: agreements:read

Returnerar hela versionskedjan för avtalet, sorterat på version ASC. Fungerar även när det anropande id:t inte är aktuell version.

Responses

  • 200 — OK
    • agreement_id: string (uuid)
    • versions: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}/signed-pdf

Get signed (stamped) PDF URL

Agreements

Scopes: agreements:read

Returns a short-lived signed URL to the final stamped PDF (with per-page footer, verification page, party details incl. BankID metadata, SHA-256 hash and QR code to public verification). Generated automatically when the last participant signs. Returns 409 if the agreement is not completed yet.

Responses

  • 200 — OK
    • url: string (uri)
    • expires_in: integer
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/lifecycle

Send or cancel an agreement

Agreements

Scopes: agreements:send, agreements:cancel

`send` kräver `agreements:send`, `cancel` kräver `agreements:cancel`.

Request body

  • action: string required
  • sender: object — Endast vid action=send. Avsändare som autosigneras. Vinner över sender som satts på draften.

Responses

  • 200 — OK
    • ok: boolean
    • status: string
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/participants

Add participant (draft or live agreement)

Agreements

Scopes: agreements:create

Add a signer or reviewer. For agreements in `sent`/`partially_signed`, the new participant is issued a signing link and an invite email is sent immediately. For drafts, they are added without a link (link generated on `send`).

Request body

  • name: string required
  • email: string (email) required
  • role: string
  • order: integer
  • job_title: string
  • phone: string
  • personal_id_masked: string
  • notifications_enabled: boolean
Example
{
  "name": "Anna Andersson",
  "email": "anna@acme.se",
  "role": "signer",
  "order": 0,
  "job_title": "VD",
  "phone": "+46701234567",
  "notifications_enabled": true
}

Responses

  • 201 — Created
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/participants/{pid}/decline

Decline on behalf of a participant

Agreements

Scopes: agreements:cancel

Request body

  • reason: string

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/participants/{pid}/delegate

Delegate participant to another person

Agreements

Scopes: agreements:create

Request body

  • name: string required
  • email: string (email) required
  • reason: string

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /agreements/{id}/participants/{pid}/notifications

Toggle reminder notifications for a participant

Agreements

Scopes: agreements:create

Request body

  • enabled: boolean required

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}/download

Download signed PDF

Agreements

Scopes: agreements:read

Responses

  • 200 — Signed PDF binary
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}/events

List audit events for an agreement

Agreements

Scopes: agreements:read

Responses

  • 200 — OK
    • events: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/documents/main

Attach the main PDF document to a draft

Agreements

Scopes: agreements:create

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Comments & chat

Kommentarer och deltagar-chat

GET /agreements/{id}/chat

List chat messages

Comments & chat

Scopes: agreements:read

Responses

  • 200 — OK
    • messages: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/chat

Post a chat message

Comments & chat

Scopes: agreements:create

Request body

  • body: string required
  • sender_label: string
  • sender_email: string (email)
  • participant_id: string (uuid)

Responses

  • 201 — Created
    object
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreements/{id}/comments

List comments

Comments & chat

Scopes: agreements:read

Responses

  • 200 — OK
    • comments: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreements/{id}/comments

Post a comment

Comments & chat

Scopes: agreements:create

Request body

  • body: string required
  • page: integer
  • anchor_x: number
  • anchor_y: number
  • author_label: string
  • author_email: string (email)
  • participant_id: string (uuid)

Responses

  • 201 — Created
    object
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /agreements/{id}/comments/{commentId}

Resolve or reopen a comment

Comments & chat

Scopes: agreements:create

Request body

  • resolved: boolean required

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Webhooks

Push-notiser med HMAC-signering

GET /webhooks

List webhooks

Webhooks

Requires bearer token.

Responses

  • 200 — OK
    • webhooks: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /webhooks

Register a webhook

Webhooks

Requires bearer token.

Returns the signing secret ONCE in `secret`. Store it — used to verify `X-Tidvis-Signature` (HMAC-SHA256 over the raw body). ### Exempel-callback från Tidvis ```http POST /your-webhook HTTP/1.1 Content-Type: application/json X-Tidvis-Event: agreement.signed X-Tidvis-Delivery: 9f1c3a7e-2b4d-4e6a-8c1f-1234567890ab X-Tidvis-Signature: sha256=8a2c…d4f9 { "event": "agreement.signed", "event_type": "agreement.signed", "delivery_id": "9f1c3a7e-2b4d-4e6a-8c1f-1234567890ab", "created_at": "2026-06-20T12:00:00Z", "agreement_id": "a1b2c3d4-1111-4aaa-9bbb-000000000001", "status": "signed", "participant": { "id": "b2c3d4e5-2222-4bbb-9ccc-000000000010", "email": "anna@acme.se" }, "data": { "agreement_id": "a1b2c3d4-1111-4aaa-9bbb-000000000001", "status": "signed", "participant": { "id": "b2c3d4e5-2222-4bbb-9ccc-000000000010", "email": "anna@acme.se" } } } ``` Verifiera signaturen i Node: ```ts import { createHmac, timingSafeEqual } from 'crypto'; const header = req.headers['x-tidvis-signature']; // 'sha256=…' const signature = header.replace(/^sha256=/, ''); const expected = createHmac('sha256', WEBHOOK_SECRET).update(rawBody).digest('hex'); if (!timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) throw new Error('bad signature'); ```

Request body

  • url: string (uri) required
  • events: array required
Example
{
  "url": "https://acme.se/webhooks/tidvis",
  "events": [
    "agreement.signed",
    "agreement.completed",
    "agreement.cancelled"
  ]
}

Responses

  • 201 — Created
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /webhooks/{id}

Delete a webhook

Webhooks

Requires bearer token.

Responses

  • 204 — Deleted
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Clients

API-klienter och nycklar

GET /clients

List API clients

Clients

Scopes: clients:manage

Responses

  • 200 — OK
    • clients: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /clients

Create API client

Clients

Scopes: clients:manage

Returns the client_secret ONCE.

Request body

  • name: string required
  • scopes: array
Example
{
  "name": "HubSpot-integration (produktion)",
  "scopes": [
    "agreements:read",
    "agreements:create",
    "agreements:send"
  ]
}

Responses

  • 201 — Created
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /clients/{id}/revoke

Revoke API client

Clients

Scopes: clients:manage

Responses

  • 200 — OK
    • ok: boolean
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Sub-accounts

Underkonton, medlemmar, parent-access

GET /sub-accounts

List sub-accounts under the parent

Sub-accounts

Scopes: sub_accounts:read

Endast tokens utgivna på huvudkontot (parent) får anropa sub-account-endpoints.

Responses

  • 200 — OK
    • sub_accounts: array
    • license: object
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /sub-accounts

Create sub-account

Sub-accounts

Scopes: sub_accounts:manage

Kräver aktiv årslicens (`sub_account_license_yearly`). Returnerar 403 `plan_required` om licens saknas eller alla seats är upptagna.

Request body

  • name: string required
  • org_number: string
  • inherit_parent_admins: boolean
Example
{
  "name": "Acme Bygg AB",
  "org_number": "556677-8899",
  "inherit_parent_admins": true
}

Responses

  • 201 — Created
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Licens saknas eller alla seats är upptagna
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /sub-accounts/{id}

Get sub-account

Sub-accounts

Scopes: sub_accounts:read

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /sub-accounts/{id}

Update sub-account

Sub-accounts

Scopes: sub_accounts:manage

Request body

  • name: string
  • org_number: string
  • bankid_unlimited: boolean

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /sub-accounts/{id}

Archive sub-account (GDPR — hard-delete after 30 days)

Sub-accounts

Scopes: sub_accounts:manage

Markeras `archived_at`. Cron `purge-archived-sub-accounts-daily` hard-deletar 30 dagar senare.

Responses

  • 204 — Archived
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /sub-accounts/{id}/parent-access

Toggle whether parent admins inherit access

Sub-accounts

Scopes: sub_accounts:manage

Request body

  • inherit_parent_admins: boolean required

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /sub-accounts/{id}/members

List sub-account members

Sub-accounts

Scopes: sub_accounts:members

Responses

  • 200 — OK
    • members: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /sub-accounts/{id}/members

Invite member to a sub-account

Sub-accounts

Scopes: sub_accounts:members

Request body

  • email: string (email) required
  • role: string
Example
{
  "email": "cecilia@acme.se",
  "role": "admin"
}

Responses

  • 201 — Invitation created
    • invitation: object
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
PATCH /sub-accounts/{id}/members/{memberId}

Change member role

Sub-accounts

Scopes: sub_accounts:members

409 `conflict` returneras om åtgärden lämnar underkontot utan ägare.

Request body

  • role: string required

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /sub-accounts/{id}/members/{memberId}

Remove member

Sub-accounts

Scopes: sub_accounts:members

409 `conflict` returneras om åtgärden lämnar underkontot utan ägare.

Responses

  • 204 — Removed
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Agreement templates

AI-byggda mallar från dina egna exempelavtal

GET /agreement-templates

List agreement templates

Agreement templates

Scopes: templates:read

Kräver att avtalsmodulen är aktiv på kontot (99 kr/användare/månad).

Responses

  • 200 — OK
    • templates: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 402 — Avtalsmodulen ej aktiv
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreement-templates

Create template from 2–10 example agreements

Agreement templates

Scopes: templates:manage

Skickar exempelavtal (PDF/DOCX) — AI extraherar produkter, prislogik och klausuler. Multipart eller JSON med base64.

Request body

  • name: string required
  • files: array required
Example
{
  "name": "Konsultavtal SaaS 2026",
  "files": [
    {
      "filename": "acme-2025.pdf",
      "mime": "application/pdf",
      "pdf_base64": "JVBERi0xLjQKJ..."
    },
    {
      "filename": "beta-2025.pdf",
      "mime": "application/pdf",
      "pdf_base64": "JVBERi0xLjQKJ..."
    }
  ]
}

Responses

  • 201 — Created
    • id: string (uuid)
    • status: string
    • extraction_error: string
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreement-templates/{id}

Get one template with full schema and source files

Agreement templates

Scopes: templates:read

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
DELETE /agreement-templates/{id}

Delete template and its source files

Agreement templates

Scopes: templates:manage

Responses

  • 204 — Deleted
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
POST /agreement-templates/{id}/generate

Generate a new agreement from this template

Agreement templates

Scopes: generations:create

Utan `send_for_signing`: returnerar DOCX inline (base64). Med `send_for_signing: true` + `recipients`: renderar PDF, skapar en Sign-draft, returnerar `sign_document_id`.

Request body

  • form: object required
  • send_for_signing: boolean
  • title: string
  • message: string
  • signature_method: string
  • recipients: array
Example
{
  "form": {
    "customer": {
      "company": "Acme AB",
      "orgnr": "556677-8899",
      "contact": "Anna Andersson",
      "email": "anna@acme.se"
    },
    "selections": [
      {
        "partId": "seats",
        "moduleId": "pro",
        "quantity": 5
      }
    ],
    "binding": 24,
    "startDate": "2026-07-01"
  },
  "send_for_signing": true,
  "signature_method": "bankid",
  "recipients": [
    {
      "email": "anna@acme.se",
      "name": "Anna Andersson"
    }
  ]
}

Responses

  • 201 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Agreement generations

Genererade avtal från mallar (DOCX / Sign)

GET /agreement-generations

List generated agreements

Agreement generations

Scopes: generations:read

Responses

  • 200 — OK
    • generations: array
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreement-generations/{id}

Get one generation

Agreement generations

Scopes: generations:read

Responses

  • 200 — OK
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error
GET /agreement-generations/{id}/download

Get a signed download URL for the generated PDF (10 min TTL)

Agreement generations

Scopes: generations:read

Endast tillgängligt om genereringen kopplats till ett Sign-dokument (har `storage_path`). DOCX-genereringar returneras inline direkt vid `/generate`.

Responses

  • 200 — OK
    • url: string (uri)
    • filename: string
    • expires_in: integer
  • 400 — Invalid request
  • 401 — Missing or invalid bearer token
  • 403 — Forbidden — missing scope, wrong plan, or sub-account license required
  • 404 — Not found
  • 409 — Conflict
  • 429 — Rate limit exceeded
  • 500 — Server error

Untagged

PARAMETERS /agreements/{id}

PARAMETERS /agreements/{id}/versions

PARAMETERS /agreements/{id}/signed-pdf

PARAMETERS /agreements/{id}/lifecycle

PARAMETERS /agreements/{id}/participants

PARAMETERS /agreements/{id}/participants/{pid}/decline

PARAMETERS /agreements/{id}/participants/{pid}/delegate

PARAMETERS /agreements/{id}/participants/{pid}/notifications

PARAMETERS /agreements/{id}/download

PARAMETERS /agreements/{id}/events

PARAMETERS /agreements/{id}/documents/main

PARAMETERS /agreements/{id}/chat

PARAMETERS /agreements/{id}/comments

PARAMETERS /agreements/{id}/comments/{commentId}

PARAMETERS /webhooks/{id}

PARAMETERS /clients/{id}/revoke

PARAMETERS /agreement-templates/{id}

PARAMETERS /agreement-templates/{id}/generate

PARAMETERS /agreement-generations/{id}

PARAMETERS /agreement-generations/{id}/download

PARAMETERS /sub-accounts/{id}

PARAMETERS /sub-accounts/{id}/parent-access

PARAMETERS /sub-accounts/{id}/members

PARAMETERS /sub-accounts/{id}/members/{memberId}

Schemas

Shared response and request shapes referenced above.

Error

  • error: object required

AgreementParty

  • id: string (uuid)
  • name: string
  • email: string (email)
  • role: string
  • order: integer
  • job_title: string
  • phone: string
  • personal_id_masked: string
  • notifications_enabled: boolean
  • status: string

Agreement

  • id: string (uuid)
  • status: string
  • title: string
  • message: string
  • expires_at: string (date-time)
  • parties: array
  • external_id: string
  • external_source: string
  • external_url: string (uri)
  • metadata: object
  • version: integer — Versionsnummer i kedjan (1 = första).
  • replaces_document_id: string (uuid) — Pekar på det avtal som denna version ersätter.
  • superseded_at: string (date-time) — Sätts när avtalet ersatts av en nyare version.
  • versions: array — Hela versionskedjan (endast med i responsen när avtalet ingår i en kedja, dvs `version > 1` eller är superseded).
  • auto_reminders_enabled: boolean
  • reminder_interval_days: integer
  • max_reminders: integer
  • signed_pdf_url: string (uri) — Short-lived signed URL to the stamped final PDF (only present after completion).
  • signed_at: string (date-time)
  • signed_sha256: string — Hex SHA-256 of the stamped final PDF.
  • created_at: string (date-time)
  • updated_at: string (date-time)

SubAccount

  • id: string (uuid)
  • parent_account_id: string (uuid)
  • name: string
  • org_number: string
  • plan: string
  • inherit_parent_admins: boolean
  • archived_at: string (date-time)
  • created_at: string (date-time)

SubAccountMember

  • id: string (uuid)
  • user_id: string (uuid)
  • email: string (email)
  • role: string
  • status: string
  • created_at: string (date-time)

Webhook

  • id: string (uuid)
  • url: string (uri)
  • events: array
  • secret_preview: string — First 8 chars of the signing secret
  • created_at: string (date-time)

ApiClient

  • id: string (uuid)
  • client_id: string
  • name: string
  • status: string
  • scopes: array
  • last_used_at: string (date-time)
  • created_at: string (date-time)
  • revoked_at: string (date-time)

AgreementTemplateSummary

  • id: string (uuid)
  • name: string
  • status: string
  • language: string
  • currency: string
  • source_uploads_count: integer
  • created_at: string (date-time)
  • updated_at: string (date-time)

AgreementTemplate

AgreementGeneration

  • id: string (uuid)
  • template_id: string (uuid)
  • agreement_number: string
  • monthly_total_ore: integer — Total månadsbelopp i öre inkl. moms
  • sign_document_id: string (uuid)
  • storage_path: string
  • form_state: object
  • created_at: string (date-time)