Preview an import
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
What an import would do, without doing it: how many rows are new, already contacts or invalid (with the line and reason), emails repeated in the file, and up to 200 rows as they would be saved. Writes nothing, so read:crm is enough. Requires read:crm. Refused for a key restricted to particular events. Also at POST /v1/org/{orgId}/crm/import/preview, and at POST /v1/crm/import/preview with the organization taken from the token.
Request example
curl --request POST \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/crm/import/preview' \ --header 'x-access-token: <api-token>' \ --header 'Content-Type: application/json' \ --data '{ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<string>" ]}'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/crm/import/preview', { method: 'POST', headers: { "x-access-token": "<api-token>", "Content-Type": "application/json" }, body: JSON.stringify({ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<string>" ] }),});
const data = await response.json();console.log(data);import requests
response = requests.request( "POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/crm/import/preview", headers={ "x-access-token": "<api-token>", "Content-Type": "application/json" }, json={ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<string>" ] },)
print(response.json())<?php
$curl = curl_init();
curl_setopt_array($curl, [ CURLOPT_URL => "https://public-api.sessionboard.com/v1/organization/{orgId}/crm/import/preview", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => '{ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<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/import/preview", strings.NewReader(`{ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<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/import/preview")) .header("x-access-token", "<api-token>") .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("{\n \"rows\": [\n {\n \"email\": \"jane@example.com\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"name\": \"<string>\",\n \"company\": \"<string>\",\n \"title\": \"<string>\",\n \"types\": [\n \"speaker\"\n ],\n \"tags\": [\n \"<string>\"\n ]\n }\n ],\n \"csv\": \"<string>\",\n \"mapping\": {\n \"key\": \"<string>\"\n },\n \"types\": [\n \"speaker\"\n ],\n \"tagIds\": [\n \"<string>\"\n ]\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
Send rows or csv.
rowsCrmImportRowInput | CrmImportCompanyRowInput[]People rows (
targetpeople, the default) or company rows (targetcompanies).- Max items
250
Option 1 (CrmImportRowInput)
A row in the import's field keys (the same keys a preview or discovery returns, so its rows can be sent back unchanged).
emailstring<email>requiredfirst_namestringlast_namestringnamestringA full name, instead of first and last.
companystringtitlestringtypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagsstring[]Tag names.
Option 2 (CrmImportCompanyRowInput)
A company row, sent with
targetcompanies. Matched by name; tags mark it a sponsor, an exhibitor or both.namestringrequiredwebsitestringtagsstring[]- Allowed values
"sponsor", "exhibitor"- Max items
2
csvstringCSV text with a header row (up to 250 rows on
POST …/crm/import).mappingobjectColumn → field (
email,first_name,last_name,name,company,title,types,tags), asimport/parsesuggests. Optional withrows.typesstring[]Given to every row.
- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
tagIdsstring[]Tags given to every row.
{ "rows": [ { "email": "jane@example.com", "first_name": "<string>", "last_name": "<string>", "name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "tags": [ "<string>" ] } ], "csv": "<string>", "mapping": { "key": "<string>" }, "types": [ "speaker" ], "tagIds": [ "<string>" ]}Responses
200application/json
OK
successbooleanpayloadobjectShow child attributes
totalintegernewintegerexistingintegerinvalidCrmInvalidRow[]Show child attributes
lineintegerreasonstring
duplicates_in_fileintegerrowsCrmImportRow[]- Max items
200
Show child attributes
emailstringfirst_namestring | nulllast_namestring | nullcompanystring | nulltitlestring | nulltypesstring[]- Allowed values
"speaker", "sme", "influencer", "exhibitor", "sponsor"
statusstring- Allowed values
"new", "existing", "invalid"
contact_idstring | nullWith
existing: the contact the row matches.reasonstring | nullWith
invalid: why.
401
Missing, invalid or expired token.
403application/json
SCOPE_REQUIRED: the token lacksread:crm.ORG_WIDE_TOKEN_REQUIRED: the key is restricted to particular events; use a key without an event restriction.FORBIDDEN: the token's user cannot read the organization's contacts.
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
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": { "total": 123, "new": 123, "existing": 123, "invalid": [ { "line": 123, "reason": "<string>" } ], "duplicates_in_file": 123, "rows": [ { "email": "<string>", "first_name": "<string>", "last_name": "<string>", "company": "<string>", "title": "<string>", "types": [ "speaker" ], "status": "new", "contact_id": "<string>", "reason": "<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>" } }}