Send a contract
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
Creates a contract for the contact from a published template and sends it for signature with Sessionboard e-sign: the signer is emailed a link to the signing page. This reaches someone outside the organization and cannot be taken back, only voided, so confirm the recipient with the person first. Sending makes the contact an active contact. Requires write:crm. Refused for a key restricted to particular events. Also at POST /v1/org/{orgId}/crm/contracts, and at POST /v1/crm/contracts with the organization taken from the token.
Request example
curl --request POST \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts' \ --header 'x-access-token: <api-token>' \ --header 'Content-Type: application/json' \ --data '{ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>"}'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts', { method: 'POST', headers: { "x-access-token": "<api-token>", "Content-Type": "application/json" }, body: JSON.stringify({ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>" }),});
const data = await response.json();console.log(data);import requests
response = requests.request( "POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts", headers={ "x-access-token": "<api-token>", "Content-Type": "application/json" }, json={ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>" },)
print(response.json())<?php
$curl = curl_init();
curl_setopt_array($curl, [ CURLOPT_URL => "https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => '{ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>"}', CURLOPT_HTTPHEADER => [ "x-access-token: <api-token>", "Content-Type: application/json", ],]);
$response = curl_exec($curl);curl_close($curl);
echo $response;package main
import ( "fmt" "io" "net/http" "strings")
func main() { req, _ := http.NewRequest("POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts", strings.NewReader(`{ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>"}`)) req.Header.Add("x-access-token", "<api-token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))}HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://public-api.sessionboard.com/v1/organization/{orgId}/crm/contracts")) .header("x-access-token", "<api-token>") .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("{\n \"contactId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"title\": \"<string>\",\n \"eventId\": 123,\n \"emailSubject\": \"<string>\",\n \"emailMessage\": \"<string>\"\n}")) .build();
HttpResponse<String> response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Try it
Response headers
Authorizations
x-access-tokenstringheaderOrganization API token. Generate from Organization Settings → API Tokens.
AuthorizationBearer <token>headerorOAuth 2.1 access token. Obtained via the OAuth PKCE flow at
/oauth/token.
Send one of these. See Authentication.
Path parameters
orgIdstringpathrequiredYour organization ID. Any other organization returns
404.
Request body
contactIdstringrequiredWho signs.
templateIdstringrequiredA published template, from
GET …/crm/contract-templates.titlestring- Max length
200
eventIdintegerThe event the agreement is for: its branding and variables.
emailSubjectstring- Max length
200
emailMessagestring- Max length
5000
{ "contactId": "<string>", "templateId": "<string>", "title": "<string>", "eventId": 123, "emailSubject": "<string>", "emailMessage": "<string>"}Responses
201application/json
Created
successbooleanpayloadCrmContractShow child attributes
idstringtitlestringstatusstringdelivered: the signer opened the signing page.completed: everyone signed.- Allowed values
"created", "sent", "delivered", "completed", "declined", "voided"
sourcestringHow it was sent:
nativeis Sessionboard e-sign.contactobject | nullShow child attributes
idstringnamestringemailstring<email>
templateobject | nullShow child attributes
idstringnamestring
signer_emailstring<email> | nullhas_pdfbooleanThe signed PDF is ready.
sent_atstring<date-time> | nullsigned_atstring<date-time> | nullvoided_atstring<date-time> | nullupdated_atstring<date-time>
400application/json
VALIDATION_ERROR: the body or a path id does not match the schema.
successbooleanerrorstring- Allowed values
"VALIDATION_ERROR", "SCOPE_REQUIRED", "ORG_WIDE_TOKEN_REQUIRED", "FORBIDDEN", "NOT_FOUND", "CONFLICT", "QUOTA_EXCEEDED"
codestringA more specific reason:
exists,read_only,platform_customer.messagestringrequiredcontactCrmContactWith
code: exists: the contact that has the email.Show child attributes
idstringfirst_namestringlast_namestring | nullnamestringemailstring<email>companystring | nulltitlestring | nullJob title.
avatar_urlstring | nulltypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagsCrmTag[]Show child attributes
idstringnamestring
events_countintegersessions_countintegerlast_activity_atstring<date-time> | nullactivebooleanAn active contact in the last 365 days.
sourcestring | nullWhere the contact came from.
created_atstring<date-time>hrefstringThe contact in Sessionboard CRM.
stageobject | nullThe contact's pipeline stage;
nullwhen not in the pipeline.Show child attributes
idstringlabelstring
401
Missing, invalid or expired token.
403application/json
SCOPE_REQUIRED: the token lackswrite:crm(orread:crmfor the POSTs that only read).ORG_WIDE_TOKEN_REQUIRED: the key is restricted to particular events.code: plan_read_only(orread_only): the CRM trial or plan has ended; everything can still be read.code: platform_customer: the organization works with Sessionboard on a platform contract, so its contacts are in the Sessionboard platform.code: FEATURE_NOT_ENABLED: contracts are not turned on for the organization (contracts operations only).FORBIDDENwith nocode: the token's user lacks the Contacts permission the change needs (connecting and disconnecting apps need an organization admin).
successbooleanerrorstring- Allowed values
"VALIDATION_ERROR", "SCOPE_REQUIRED", "ORG_WIDE_TOKEN_REQUIRED", "FORBIDDEN", "NOT_FOUND", "CONFLICT", "QUOTA_EXCEEDED"
codestringA more specific reason:
exists,read_only,platform_customer.messagestringrequiredcontactCrmContactWith
code: exists: the contact that has the email.Show child attributes
idstringfirst_namestringlast_namestring | nullnamestringemailstring<email>companystring | nulltitlestring | nullJob title.
avatar_urlstring | nulltypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagsCrmTag[]Show child attributes
idstringnamestring
events_countintegersessions_countintegerlast_activity_atstring<date-time> | nullactivebooleanAn active contact in the last 365 days.
sourcestring | nullWhere the contact came from.
created_atstring<date-time>hrefstringThe contact in Sessionboard CRM.
stageobject | nullThe contact's pipeline stage;
nullwhen not in the pipeline.Show child attributes
idstringlabelstring
404application/json
NOT_FOUND: orgId is not the token's organization, or the contact, tag or app is not in it.
successbooleanerrorstring- Allowed values
"VALIDATION_ERROR", "SCOPE_REQUIRED", "ORG_WIDE_TOKEN_REQUIRED", "FORBIDDEN", "NOT_FOUND", "CONFLICT", "QUOTA_EXCEEDED"
codestringA more specific reason:
exists,read_only,platform_customer.messagestringrequiredcontactCrmContactWith
code: exists: the contact that has the email.Show child attributes
idstringfirst_namestringlast_namestring | nullnamestringemailstring<email>companystring | nulltitlestring | nullJob title.
avatar_urlstring | nulltypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagsCrmTag[]Show child attributes
idstringnamestring
events_countintegersessions_countintegerlast_activity_atstring<date-time> | nullactivebooleanAn active contact in the last 365 days.
sourcestring | nullWhere the contact came from.
created_atstring<date-time>hrefstringThe contact in Sessionboard CRM.
stageobject | nullThe contact's pipeline stage;
nullwhen not in the pipeline.Show child attributes
idstringlabelstring
409application/json
CONFLICT: the contract is not in a state that allows this (already completed, declined or voided), or the contact already has an open pipeline entry for that event. Nothing was changed.
successbooleanerrorstring- Allowed values
"VALIDATION_ERROR", "SCOPE_REQUIRED", "ORG_WIDE_TOKEN_REQUIRED", "FORBIDDEN", "NOT_FOUND", "CONFLICT", "QUOTA_EXCEEDED"
codestringA more specific reason:
exists,read_only,platform_customer.messagestringrequiredcontactCrmContactWith
code: exists: the contact that has the email.Show child attributes
idstringfirst_namestringlast_namestring | nullnamestringemailstring<email>companystring | nulltitlestring | nullJob title.
avatar_urlstring | nulltypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagsCrmTag[]Show child attributes
idstringnamestring
events_countintegersessions_countintegerlast_activity_atstring<date-time> | nullactivebooleanAn active contact in the last 365 days.
sourcestring | nullWhere the contact came from.
created_atstring<date-time>hrefstringThe contact in Sessionboard CRM.
stageobject | nullThe contact's pipeline stage;
nullwhen not in the pipeline.Show child attributes
idstringlabelstring
429
The token's request limit (100 requests per 15 minutes by default) or, for writes, its daily write quota. Wait Retry-After seconds.
Retry-AfterintegerheaderSeconds to wait before retrying.
Response examples
{ "success": true, "payload": { "id": "<string>", "title": "<string>", "status": "created", "source": "<string>", "contact": { "id": "<string>", "name": "<string>", "email": "jane@example.com" }, "template": { "id": "<string>", "name": "<string>" }, "signer_email": "jane@example.com", "has_pdf": true, "sent_at": "2026-01-15T09:30:00Z", "signed_at": "2026-01-15T09:30:00Z", "voided_at": "2026-01-15T09:30:00Z", "updated_at": "2026-01-15T09:30:00Z" }}{ "success": false, "error": "VALIDATION_ERROR", "code": "<string>", "message": "<string>", "contact": { "id": "<string>", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "email": "jane@example.com", "company": "<string>", "title": "<string>", "avatar_url": "<string>", "types": [ "speaker" ], "tags": [ { "id": "<string>", "name": "<string>" } ], "events_count": 123, "sessions_count": 123, "last_activity_at": "2026-01-15T09:30:00Z", "active": true, "source": "<string>", "created_at": "2026-01-15T09:30:00Z", "href": "<string>", "stage": { "id": "<string>", "label": "<string>" } }}{ "success": false, "error": "VALIDATION_ERROR", "code": "<string>", "message": "<string>", "contact": { "id": "<string>", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "email": "jane@example.com", "company": "<string>", "title": "<string>", "avatar_url": "<string>", "types": [ "speaker" ], "tags": [ { "id": "<string>", "name": "<string>" } ], "events_count": 123, "sessions_count": 123, "last_activity_at": "2026-01-15T09:30:00Z", "active": true, "source": "<string>", "created_at": "2026-01-15T09:30:00Z", "href": "<string>", "stage": { "id": "<string>", "label": "<string>" } }}{ "success": false, "error": "VALIDATION_ERROR", "code": "<string>", "message": "<string>", "contact": { "id": "<string>", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "email": "jane@example.com", "company": "<string>", "title": "<string>", "avatar_url": "<string>", "types": [ "speaker" ], "tags": [ { "id": "<string>", "name": "<string>" } ], "events_count": 123, "sessions_count": 123, "last_activity_at": "2026-01-15T09:30:00Z", "active": true, "source": "<string>", "created_at": "2026-01-15T09:30:00Z", "href": "<string>", "stage": { "id": "<string>", "label": "<string>" } }}{ "success": false, "error": "VALIDATION_ERROR", "code": "<string>", "message": "<string>", "contact": { "id": "<string>", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "email": "jane@example.com", "company": "<string>", "title": "<string>", "avatar_url": "<string>", "types": [ "speaker" ], "tags": [ { "id": "<string>", "name": "<string>" } ], "events_count": 123, "sessions_count": 123, "last_activity_at": "2026-01-15T09:30:00Z", "active": true, "source": "<string>", "created_at": "2026-01-15T09:30:00Z", "href": "<string>", "stage": { "id": "<string>", "label": "<string>" } }}