Quick start
Base URL: https://tidvis.se/api/public/v1. All calls use JSON. The Public API is part of the Enterprise plan.
- 1. Create an API client under Sign → Settings → API and save your
client_idandclient_secret. - 2. Exchange them for an
access_tokenvia OAuth2 client credentials. - 3. Create an agreement, upload a PDF, add participants and send.
curl -X POST https://tidvis.se/api/public/v1/oauth/access-token \
-H "Content-Type: application/json" \
-d '{"client_id":"tvc_...","client_secret":"tvs_..."}'Authentication
OAuth2 client credentials. Exchange client_id+client_secret for a JWT valid for 1 hour. Send Authorization: Bearer <access_token> on every subsequent call.
/oauth/access-tokenIssue an access token (1h TTL).
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": "2026-06-07T13:00:00.000Z"
}/oauth/access-tokenRevoke the current token (requires Authorization header).
Agreements
/agreementsCreate a draft agreement (status: draft).
curl -X POST https://tidvis.se/api/public/v1/agreements \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Employment contract Anna","expires_in_days":14,"bankid_required":true}'/agreementsList agreements. Supports ?status, ?limit, ?cursor.
/agreements/:idFetch an agreement with participants and status.
/agreements/:id/eventsAudit trail (sent, viewed, signed, completed...).
/agreements/:id/downloadFetch the signed PDF (returns a signed URL or binary content).
Participants
/agreements/:id/participantsAdd a signer (only in draft state).
{
"name": "Anna Andersson",
"email": "anna@example.com",
"role": "signer"
}PDF documents
/agreements/:id/documents/mainUpload the main document. Accepts application/pdf (binary) or JSON with base64.
# JSON / base64
curl -X PUT https://tidvis.se/api/public/v1/agreements/$ID/documents/main \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"filename":"agreement.pdf","content_base64":"JVBERi0..."}'
# Or binary
curl -X PUT https://tidvis.se/api/public/v1/agreements/$ID/documents/main \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/pdf" \
--data-binary @agreement.pdfLifecycle
/agreements/:id/lifecycleSend or cancel an agreement.
{"action": "send"} // or "cancel"BankID
You can require Swedish BankID signing per agreement. Set bankid_required: true on creation (or via PATCH before sending). When the agreement is sent each participant signs with BankID on mobile or desktop instead of drawing a signature.
Requirements
- The account must have the Sign Pro plan and the BankID add-on enabled.
- Pricing: 100 BankID signatures included per month, then 5 SEK/signature.
- Without the add-on,
POST /agreements/:id/lifecyclewithaction: "send"returns402 bankid_disabled.
Create a BankID agreement
curl -X POST https://tidvis.se/api/public/v1/agreements \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Employment contract Anna",
"bankid_required": true
}'Response (abbreviated):
{
"id": "agr_...",
"status": "draft",
"bankid_required": true,
"document": { "uploaded": false, "sha256": null },
"participants": []
}Webhook payload when BankID is used
For agreements with bankid_required: true, the agreement.signed event is enriched with a signature block. For privacy reasons, neither personal identity numbers, certificates nor OCSP responses are exposed via the API or webhooks.
{
"event": "agreement.signed",
"agreement_id": "agr_...",
"participant": { "id": "p_...", "email": "anna@example.com" },
"signature": {
"method": "bankid",
"signer_name": "Anna Andersson",
"signed_at": "2026-06-11T08:42:11.000Z"
}
}Webhooks
Tidvis delivers events to your URL via POST JSON. Every request is HMAC-SHA256 signed in the header X-Tidvis-Signature: sha256=<hex> based on your signing_secret and the raw body. Failed deliveries are retried with exponential backoff for up to 24h.
/webhooksRegister a webhook.
{
"client_id": "<api_client uuid>",
"url": "https://your-app.com/webhooks/tidvis",
"events": ["agreement.sent","agreement.signed","agreement.completed"]
}/webhooksList registered webhooks.
/webhooks/:idRemove a webhook.
Events
agreement.sentagreement.viewedagreement.signedagreement.completedagreement.cancelledagreement.expired
For agreements with bankid_required: true, the agreement.signed/agreement.completed events include a signature block. See BankID.
Verify signature (Node.js)
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const given = (header || "").replace(/^sha256=/, "");
return timingSafeEqual(Buffer.from(expected), Buffer.from(given));
}Error codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed input. |
| 401 | unauthorized | Missing or invalid token. |
| 402 | plan_required | Account lacks the Enterprise plan. Includes upgrade_url. |
| 402 | bankid_disabled | Agreement has bankid_required: true but the account lacks the BankID add-on. |
| 403 | forbidden | No permission for the resource. |
| 404 | not_found | Resource not found. |
| 409 | conflict | Invalid state transition (e.g. sending an already sent agreement). |
| 429 | rate_limited | Too many requests. |
| 500 | server_error | Server error – retry. |
Rate limits
Default: 60 requests/minute per client and 600/hour for uploads. When exceeded you'll get 429 rate_limited with a Retry-After header. Need more? Contact us.
MCP & AI agents
Tidvis Sign exposes a Model Context Protocol server so AI agents (ChatGPT, Claude Desktop, custom agents) can create, send and track agreements with a single tool call. Discovery manifest at /.well-known/mcp.json. A dedicated landing page lives at /en/developers/mcp.
Endpoint
POST https://tidvis.se/api/mcp
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json, text/event-streamScopes
API tokens can be restricted to specific scopes. MCP access requires mcp:connect plus any combination of:
agreements:read– fetch agreements & eventsagreements:create– create drafts & participantsagreements:send– send agreements for signingagreements:cancel– cancel agreementsbilling:checkout– generate checkout linkmcp:connect– required for MCP access
Available tools
tidvis_sign_create_agreementtidvis_sign_add_participanttidvis_sign_upload_pdftidvis_sign_send_agreementtidvis_sign_cancel_agreementtidvis_sign_get_agreementtidvis_sign_list_eventstidvis_sign_create_checkout
Claude Desktop configuration
{
"mcpServers": {
"tidvis-sign": {
"url": "https://tidvis.se/api/mcp",
"headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
}
}
}Agent checkout & pay-per-agreement
Two ways for an agent to let the end customer pay:
- Sign Pro (subscription) – monthly fee per seat, unlimited agreements. Use
tidvis_sign_create_checkoutwithproduct: "sign_pro_monthly"and the desired number of seats. - Pay-per-agreement – 19 SEK/agreement as prepaid credits, ideal for low-volume agents. Use
product: "sign_per_agreement"and a credit count (1–500). Credits are consumed automatically whensend_agreementruns on free-plan accounts.
The checkout tool returns a Stripe-hosted URL the agent shows to the end customer. A 402 plan_required on send_agreement means the account has neither credits nor Sign Pro – the response includes an upgrade_url the agent can link to.