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.