Skip to main content

Quickstart: Send your first signing

This walkthrough builds a minimal integration that creates a signing, uploads a PDF, adds a recipient, and dispatches the package. It uses the Client Credentials flow and cURL for clarity, but you can translate the same steps into any HTTP client.

Prerequisites

  • An active Krebit Sign tenant.
  • An OAuth application with client credentials (client_id, client_secret).
  • A PDF file (document.pdf) under 10 MB without passwords or existing signatures.
  • A recipient ready to receive signing notifications.

Set helpful environment variables before proceeding:

export KREBIT_DOMAIN="yourco.krebit.se"
export KREBIT_API="https://${KREBIT_DOMAIN}/api/1.0"
export KREBIT_CLIENT_ID="YOUR_CLIENT_ID"
export KREBIT_CLIENT_SECRET="YOUR_CLIENT_SECRET"

Step 1 – Obtain an access token

ACCESS_TOKEN=$(curl --silent --request POST \
--url https://${KREBIT_DOMAIN}/oauth/token \
--header 'Content-Type: application/json' \
--data "{
\"grant_type\": \"client_credentials\",
\"client_id\": \"${KREBIT_CLIENT_ID}\",
\"client_secret\": \"${KREBIT_CLIENT_SECRET}\"
}" | jq -r '.access_token')

If you do not have jq, run the request manually and copy the access_token. Tokens typically expire after one hour; refresh as needed.

Step 2 – Create a draft signing

SIGNING_ID=$(curl --silent --request POST \
--url ${KREBIT_API}/signings \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"name": "Demo agreement",
"language": "EN",
"signing_order": "sequential",
"message": "Please sign by Friday."
}' | jq -r '.id')

Drafts are fully editable. If you receive a 400 response, review the error payload for validation messages (for example, unsupported language or message length over 400 characters).

Step 3 – Upload a PDF document

DOCUMENT_ID=$(curl --silent --request POST \
--url ${KREBIT_API}/signings/${SIGNING_ID}/documents \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--form selected_file=@document.pdf | jq -r '.id')

PDF validation happens server-side. A 422 status typically indicates the file is protected, too large, or already signed.

Step 4 – Add a recipient

RECIPIENT_ID=$(curl --silent --request POST \
--url ${KREBIT_API}/signings/${SIGNING_ID}/recipients \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"first_name": "Ada",
"last_name": "Lovelace",
"email": "ada@example.com",
"signing_method": "email",
"order": 1
}' | jq -r '.id')

For sequential signings, ensure order values are unique and start at 1. Some signing methods require phone or identification fields—refer to the generated API reference for specifics.

Step 5 – Send the signing package

curl --request POST \
--url ${KREBIT_API}/signings/${SIGNING_ID}/send \
--header "Authorization: Bearer ${ACCESS_TOKEN}"

Sending transitions the signing out of draft mode and dispatches notifications. If the response returns 400 with cannot_be_sent, verify that at least one document and recipient exist and that the signing is still editable.

Step 6 – Track progress

Use GET /api/1.0/signings/{id} to read the signing status, or list outstanding recipients via GET /api/1.0/signings/{id}/recipients.

curl --request GET \
--url ${KREBIT_API}/signings/${SIGNING_ID} \
--header "Authorization: Bearer ${ACCESS_TOKEN}" | jq '{
name: .name,
is_draft: .is_draft,
is_completed: .is_completed,
cancelled_at: .cancelled_at,
documents: (.documents[] | {name, completed_at})
}'

Use reminders when recipients stall:

curl --request POST \
--url ${KREBIT_API}/signings/${SIGNING_ID}/recipients/${RECIPIENT_ID}/remind \
--header "Authorization: Bearer ${ACCESS_TOKEN}"

Reminders respect the 14-day invitation expiry and silently skip recipients who have already completed their signing step.

Optional – Download the sealed PDF

After all recipients finish, download the signed version:

curl --request GET \
--url ${KREBIT_API}/signings/${SIGNING_ID}/documents/${DOCUMENT_ID}/download-signed \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--output signed-agreement.pdf

download-signed returns 404 until the document is fully signed. Poll sparingly or subscribe to webhooks for real-time updates.

Example Node.js integration

The snippet below wraps the same workflow in Node.js using axios and form-data. It is intentionally concise—add robust error handling and retries before using it in production.

import axios from 'axios';
import FormData from 'form-data';
import fs from 'node:fs';

const baseUrl = `https://${process.env.KREBIT_DOMAIN}`;
const api = axios.create({
baseURL: `${baseUrl}/api/1.0`,
headers: { 'Accept': 'application/json' },
});

async function authenticate() {
const { data } = await axios.post(`${baseUrl}/oauth/token`, {
grant_type: 'client_credentials',
client_id: process.env.KREBIT_CLIENT_ID,
client_secret: process.env.KREBIT_CLIENT_SECRET,
});
api.defaults.headers.common.Authorization = `Bearer ${data.access_token}`;
}

async function run() {
await authenticate();

const { data: signing } = await api.post('/signings', {
name: 'Demo agreement',
language: 'EN',
signing_order: 'sequential',
message: 'Please sign by Friday.',
});

const form = new FormData();
form.append('selected_file', fs.createReadStream('./document.pdf'));
await api.post(`/signings/${signing.id}/documents`, form, {
headers: form.getHeaders(),
});

await api.post(`/signings/${signing.id}/recipients`, {
first_name: 'Ada',
last_name: 'Lovelace',
email: 'ada@example.com',
signing_method: 'email',
order: 1,
});

await api.post(`/signings/${signing.id}/send`);
console.log('Signing dispatched:', signing.id);
}

run().catch((error) => {
console.error('Krebit workflow failed', error.response?.data || error.message);
process.exit(1);
});

Where to go next

  • Review the Signings guide for lifecycle best practices.
  • Explore webhook setup to receive completion events in real time.
  • Browse the generated API reference from the sidebar whenever you need parameter or schema details.