Create a custom source
curl --request POST \
--url https://api.seynlabs.com/v1/sources \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Internal CRM",
"entityTypes": [
"deal",
"account",
"activity"
],
"description": "Deals and activity from our in-house CRM"
}
'import requests
url = "https://api.seynlabs.com/v1/sources"
payload = {
"name": "Internal CRM",
"entityTypes": ["deal", "account", "activity"],
"description": "Deals and activity from our in-house CRM"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Internal CRM',
entityTypes: ['deal', 'account', 'activity'],
description: 'Deals and activity from our in-house CRM'
})
};
fetch('https://api.seynlabs.com/v1/sources', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.seynlabs.com/v1/sources",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Internal CRM',
'entityTypes' => [
'deal',
'account',
'activity'
],
'description' => 'Deals and activity from our in-house CRM'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.seynlabs.com/v1/sources"
payload := strings.NewReader("{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <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))
}HttpResponse<String> response = Unirest.post("https://api.seynlabs.com/v1/sources")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.seynlabs.com/v1/sources")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "b6f1c0de-1f2a-4c3b-9d4e-5a6b7c8d9e0f",
"type": "custom_api",
"name": "Internal CRM",
"status": "active",
"createdAt": "2026-06-12T16:20:00Z"
},
"meta": {
"requestId": "f0e1d2c3-b4a5-4968-8778-695a4b3c2d1e"
}
}Ingestion
Create a custom source
Register a source for any system Seyn has no prebuilt connector for.
POST
/
v1
/
sources
Create a custom source
curl --request POST \
--url https://api.seynlabs.com/v1/sources \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Internal CRM",
"entityTypes": [
"deal",
"account",
"activity"
],
"description": "Deals and activity from our in-house CRM"
}
'import requests
url = "https://api.seynlabs.com/v1/sources"
payload = {
"name": "Internal CRM",
"entityTypes": ["deal", "account", "activity"],
"description": "Deals and activity from our in-house CRM"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Internal CRM',
entityTypes: ['deal', 'account', 'activity'],
description: 'Deals and activity from our in-house CRM'
})
};
fetch('https://api.seynlabs.com/v1/sources', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.seynlabs.com/v1/sources",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Internal CRM',
'entityTypes' => [
'deal',
'account',
'activity'
],
'description' => 'Deals and activity from our in-house CRM'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.seynlabs.com/v1/sources"
payload := strings.NewReader("{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <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))
}HttpResponse<String> response = Unirest.post("https://api.seynlabs.com/v1/sources")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.seynlabs.com/v1/sources")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Internal CRM\",\n \"entityTypes\": [\n \"deal\",\n \"account\",\n \"activity\"\n ],\n \"description\": \"Deals and activity from our in-house CRM\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "b6f1c0de-1f2a-4c3b-9d4e-5a6b7c8d9e0f",
"type": "custom_api",
"name": "Internal CRM",
"status": "active",
"createdAt": "2026-06-12T16:20:00Z"
},
"meta": {
"requestId": "f0e1d2c3-b4a5-4968-8778-695a4b3c2d1e"
}
}Step one of bringing your own data. Register a custom source and you get back a
sourceId to push records to via Ingest records.
The optional entityTypes hint lists the kinds of records you’ll send (deal, ticket, task). It improves how Seyn routes normalization, but you can ingest entity types you didn’t declare.
Requires an API key with the ingest scope.Authorizations
Bearer token from app.seynlabs.com → Settings → API Keys.
Send as Authorization: Bearer sk_live_....
Headers
Optional. Reuse the same key when retrying so a source is created only once.
Body
application/json
⌘I