Skip to main content

Create a contract from a template

Create a contract from a template, fill in the details you already know, and send it for signing. Recipients can complete the remaining fields before signing the generated PDF.

These endpoints require the contracts feature to be enabled for your organization. If you already have a finished PDF, follow Send a PDF.

Prepare a template​

Create your template in Krebit Sign. For fields your integration will populate, open Field settings → Advanced settings → Field key and assign an optional key such as customer_name.

Keys must start with a lowercase letter, contain only lowercase letters, numbers and underscores, and be unique within the template. The maximum length is 64 characters. Keys are copied into new contracts; later template changes do not change contracts already created from it.

Fields without keys can still be addressed by their UUIDs. Use the template field UUID when creating a contract, and the new contract field UUID when updating it. Named keys avoid having to map these different IDs.

1. Find the template and its fields​

The examples use cURL and jq. Obtain an access token using the authentication guide, then set:

export KREBIT_API="https://yourco.krebit.se/api/1.0"
export ACCESS_TOKEN="YOUR_ACCESS_TOKEN"

List templates and choose the template you want to use:

curl --fail-with-body --silent --show-error \
"${KREBIT_API}/contract-templates?limit=20&page=1" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' | jq '.data[] | {id, name}'

Fetch its field definitions before building your request:

export TEMPLATE_ID="YOUR_TEMPLATE_UUID"

curl --fail-with-body --silent --show-error \
"${KREBIT_API}/contract-templates/${TEMPLATE_ID}" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' | jq '.fields'

Each input field includes its id, optional key, label, type, current value, and required and locked settings. Select and radio fields also include choices. List responses contain summaries; use the detail endpoint to read fields.

2. Create a signing draft and contract​

Create a signing to hold the contract:

SIGNING_ID=$(curl --fail-with-body --silent --show-error --request POST \
"${KREBIT_API}/signings" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"name":"Service agreement","language":"EN","signing_order":"sequential"}' \
| jq -r '.id')

Create a contract from the template. This example assumes it has a field with the key customer_name; replace that key with one from your template, or omit fields to use its defaults.

CONTRACT_ID=$(curl --fail-with-body --silent --show-error --request POST \
"${KREBIT_API}/signings/${SIGNING_ID}/contracts" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data "{\"template_id\":\"${TEMPLATE_ID}\",\"name\":\"Service agreement\",\"fields\":[{\"key\":\"customer_name\",\"value\":\"Example AB\"}]}" \
| jq -r '.id')

The 201 response contains the contract and its fields. Save the signing and contract IDs for subsequent requests. Each creation request creates a new contract, so check your stored IDs and the signing's contract list before retrying a request with an uncertain outcome:

GET /api/1.0/signings/{signing}/contracts

3. Update values while the signing is a draft​

You can supply initial values during creation, update them later, or let recipients complete editable fields. To change a value before sending:

curl --fail-with-body --silent --show-error --request PUT \
"${KREBIT_API}/signings/${SIGNING_ID}/contracts/${CONTRACT_ID}/fields" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"fields":[{"key":"customer_name","value":"Updated Example AB"}]}'

When supplying fields:

  • Use exactly one of key or id for each field, together with value.
  • Values are strings of up to 255 characters, or null to clear a value. Omitted fields keep their current values or template defaults.
  • Email fields require valid email addresses. Select and radio values must match a listed choice.
  • A locked field can be prefilled through the API, but recipients cannot edit it. Prefill any locked, required fields before sending.
  • An invalid or duplicate field rejects the entire update with 422; no fields in that request are changed.

4. Add a recipient and send​

Use the same recipient and send endpoints as a signing with uploaded PDFs:

curl --fail-with-body --silent --show-error --request POST \
"${KREBIT_API}/signings/${SIGNING_ID}/recipients" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"first_name":"Ada","last_name":"Lovelace","email":"ada@example.com","signing_method":"email"}'

curl --fail-with-body --silent --show-error --request POST \
"${KREBIT_API}/signings/${SIGNING_ID}/send" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json'

A contract can be sent without uploading a separate PDF. The recipient completes the required fields and confirms the contract to generate the document for signing. API field updates are only available while the signing and contract are editable drafts.

5. Retrieve the signed values and PDF​

Read the contract to retrieve its field values, including those entered by recipients:

CONTRACT=$(curl --fail-with-body --silent --show-error \
"${KREBIT_API}/signings/${SIGNING_ID}/contracts/${CONTRACT_ID}" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json')

printf '%s' "$CONTRACT" | jq '{signed_at, fields: [.fields[] | {id, key, label, value}]}'

The contract response distinguishes these stages:

FieldMeaning
completed_atThe contract has been finalized as a PDF.
generated_document_idThe generated document's ID, available after PDF creation.
signed_atAll signatures on that document are complete.

Each is null until the corresponding stage is reached. Use signed_at to check signing completion, then download the signed PDF using generated_document_id:

DOCUMENT_ID=$(printf '%s' "$CONTRACT" | jq -r '.generated_document_id')

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

Find a contract from a document or webhook​

Document responses include contract_id. When it is not null, combine it with the signing ID to retrieve the source contract and its fields.

The signing.document.completed webhook includes data.document.signing_id and data.document.contract_id. After verifying the webhook, use them to call:

GET /api/1.0/signings/{signing_id}/contracts/{contract_id}

The webhook signals completion; fetch the contract for the field values. A null contract_id means there is no contract link to follow, for example for an uploaded PDF.

Next step​

Follow Webhooks and results to automate this retrieval. The signing lifecycle guide covers multiple recipients, reminders, and cancellation.

API reference​