Create squad
https://app.sulus.ai/api/squads
Create and publish a squad (writes to the live platform first)
Authentication
Send a bearer token created on your dashboard's Developer page:
Authorization: Bearer <YOUR_API_KEY>
Request body
name
string
Required
Squad display name.
required|string|max:100squads.nameuser_id
integer
Optional
Nullable
Owner assignment — honoured only for admin roles.
nullable|integer|exists:users,idsquads.user_idmembers
array
Required
The squad's assistants. The first member answers the call.
required|array|min:1squads.membersmembers.*.assistantId
string
Required
The member assistant's public id (UUID).
required|stringsquads.membersmembers.*.assistantOverrides
object
Optional
Nullable
Per-member overrides applied while this member is live (see Fields page).
nullable|arraysquads.membersmembers.*.assistantDestinations
array
Optional
Nullable
Handoff targets this member can transfer the call to.
nullable|arraysquads.membersmembers.*.assistantDestinations.*.type
string
Optional
Nullable
nullable|string|in:assistantsquads.membersmembers.*.assistantDestinations.*.assistantName
string
Required
Name of the destination member.
required|string|max:255squads.membersmembers.*.assistantDestinations.*.message
string
Optional
Nullable
What is said while transferring.
nullable|string|max:1000squads.membersmembers.*.assistantDestinations.*.description
string
Optional
Nullable
When the transfer should happen.
nullable|string|max:2000squads.membersmembers.*.assistantDestinations.*.transferMode
string
Optional
Nullable
How conversation history carries into the destination.
nullable|string|in:rolling-history,swap-system-message-in-history,swap-system-message-in-history-and-remove-transfer-tool-messages,delete-historysquads.membersmembers.*.assistantDestinations.*.assistantId
string
Optional
Nullable
nullable|stringsquads.membersmembers.*.position
object
Optional
Nullable
Canvas position in the visual builder (UI-only).
nullable|array (x/y: nullable|numeric)squads.membersmembersOverrides
object
Optional
Nullable
Squad-wide overrides applied to every member.
nullable|arraysquads.members_overridesvariableValues
object
Optional
Nullable
Template variable values shared by the squad.
nullable|arraysquads.variable_valuesmetadata
object
Optional
Nullable
Stored locally only — never forwarded to the live platform.
nullable|arraysquads.metadataErrors
| Status | Meaning | Body |
|---|---|---|
403 |
Assigning another owner without admin rights | {"success":false,"message":"You may only create squads for yourself."} |
422 |
Target owner unknown | {"success":false,"message":"Target user not found."} |
403 |
Target owner outside your account | {"success":false,"message":"Target user is outside your reseller."} |
422 |
Composition invalid for the live platform | {"success":false,"message":"Squad payload invalid: <detail>"} |
502 |
Live platform write failed | |
500 |
Live write succeeded but local mirror failed — response carries upstream_id for support | |
422 |
Validation failed | {"message":"…","errors":{"field":["…"]}} |
403 |
Workspace permission denied | |
401 |
Missing or invalid bearer token | |
403 |
Feature squads not enabled for the account |
Notes
- Validation messages include: "Squad name is required.", "A squad needs at least one assistant.", "Each member must reference an assistant."
- metadata is stored locally only — never forwarded to the live platform.
- model/voice/transcriber engine selection (provider/model/voiceId values) is platform-managed — the values shown are illustrative placeholders, not an exhaustive allow-list.
- coreData mirrors the live voice platform's own squad object; only its id is guaranteed to appear — the rest of its shape is internal and not part of the documented contract (see Overview).
curl --request POST \
--url https://app.sulus.ai/api/squads \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"name": "Front desk",
"user_id": null,
"members": [
{
"assistantId": "a1b2c3d4-1e2f-4a3b-8c9d-0e1f2a3b4c5d",
"assistantOverrides": {
"name": "Reception",
"description": "Front-desk greeter",
"firstMessage": "Thanks for calling, how can I help?",
"firstMessageMode": "assistant-speaks-first",
"voicemailMessage": "Please leave a message after the tone.",
"endCallMessage": "Thanks for calling, goodbye!",
"model": {"provider": "default", "model": "standard", "temperature": 0.7},
"voice": {"provider": "default", "voiceId": "voice-standard-1"},
"transcriber": {"provider": "default", "model": "standard", "language": "en"},
"variableValues": {"business_name": "Acme Dental"},
"metadata": {"note": "front desk member"}
},
"assistantDestinations": [
{
"type": "assistant",
"assistantName": "Booking",
"message": "One moment, transferring you.",
"description": "Caller wants to book an appointment",
"transferMode": "rolling-history",
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e"
}
],
"position": {"x": 120.5, "y": 240.0}
},
{
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e",
"assistantOverrides": {"name": "Booking"},
"position": {"x": 420.0, "y": 240.0}
}
],
"membersOverrides": {
"voicemailMessage": "Please leave a message after the tone.",
"variableValues": {"business_name": "Acme Dental"}
},
"variableValues": {"business_name": "Acme Dental", "business_hours": "Mon-Fri 9am-5pm"},
"metadata": {"template_id": 5, "personality_id": 16, "tags": ["dental", "front-desk"]}
}'
import requests
url = "https://app.sulus.ai/api/squads"
headers = {"Authorization": "Bearer <YOUR_API_KEY>"}
payload = {
"name": "Front desk",
"user_id": null,
"members": [
{
"assistantId": "a1b2c3d4-1e2f-4a3b-8c9d-0e1f2a3b4c5d",
"assistantOverrides": {
"name": "Reception",
"description": "Front-desk greeter",
"firstMessage": "Thanks for calling, how can I help?",
"firstMessageMode": "assistant-speaks-first",
"voicemailMessage": "Please leave a message after the tone.",
"endCallMessage": "Thanks for calling, goodbye!",
"model": {"provider": "default", "model": "standard", "temperature": 0.7},
"voice": {"provider": "default", "voiceId": "voice-standard-1"},
"transcriber": {"provider": "default", "model": "standard", "language": "en"},
"variableValues": {"business_name": "Acme Dental"},
"metadata": {"note": "front desk member"}
},
"assistantDestinations": [
{
"type": "assistant",
"assistantName": "Booking",
"message": "One moment, transferring you.",
"description": "Caller wants to book an appointment",
"transferMode": "rolling-history",
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e"
}
],
"position": {"x": 120.5, "y": 240.0}
},
{
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e",
"assistantOverrides": {"name": "Booking"},
"position": {"x": 420.0, "y": 240.0}
}
],
"membersOverrides": {
"voicemailMessage": "Please leave a message after the tone.",
"variableValues": {"business_name": "Acme Dental"}
},
"variableValues": {"business_name": "Acme Dental", "business_hours": "Mon-Fri 9am-5pm"},
"metadata": {"template_id": 5, "personality_id": 16, "tags": ["dental", "front-desk"]}
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
url := "https://app.sulus.ai/api/squads"
payload := strings.NewReader(`{
"name": "Front desk",
"user_id": null,
"members": [
{
"assistantId": "a1b2c3d4-1e2f-4a3b-8c9d-0e1f2a3b4c5d",
"assistantOverrides": {
"name": "Reception",
"description": "Front-desk greeter",
"firstMessage": "Thanks for calling, how can I help?",
"firstMessageMode": "assistant-speaks-first",
"voicemailMessage": "Please leave a message after the tone.",
"endCallMessage": "Thanks for calling, goodbye!",
"model": {"provider": "default", "model": "standard", "temperature": 0.7},
"voice": {"provider": "default", "voiceId": "voice-standard-1"},
"transcriber": {"provider": "default", "model": "standard", "language": "en"},
"variableValues": {"business_name": "Acme Dental"},
"metadata": {"note": "front desk member"}
},
"assistantDestinations": [
{
"type": "assistant",
"assistantName": "Booking",
"message": "One moment, transferring you.",
"description": "Caller wants to book an appointment",
"transferMode": "rolling-history",
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e"
}
],
"position": {"x": 120.5, "y": 240.0}
},
{
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e",
"assistantOverrides": {"name": "Booking"},
"position": {"x": 420.0, "y": 240.0}
}
],
"membersOverrides": {
"voicemailMessage": "Please leave a message after the tone.",
"variableValues": {"business_name": "Acme Dental"}
},
"variableValues": {"business_name": "Acme Dental", "business_hours": "Mon-Fri 9am-5pm"},
"metadata": {"template_id": 5, "personality_id": 16, "tags": ["dental", "front-desk"]}
}`)
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <YOUR_API_KEY>")
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))
}
{
"success": true,
"data": {
"name": "Front desk",
"external_squad_id": "e5f6a7b8-1c2d-4e3f-9a8b-7c6d5e4f3a2b",
"status": "published",
"user_id": 42,
"created_by": 42,
"reseller_id": "f1e2d3c4-b5a6-4978-8901-234567890abc",
"workspace_id": 7,
"members": [
{
"assistantId": "a1b2c3d4-1e2f-4a3b-8c9d-0e1f2a3b4c5d",
"assistantOverrides": {
"name": "Reception",
"firstMessage": "Thanks for calling, how can I help?"
},
"assistantDestinations": [
{
"type": "assistant",
"assistantName": "Booking",
"message": "One moment, transferring you.",
"description": "Caller wants to book an appointment",
"transferMode": "rolling-history",
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e"
}
],
"position": {
"x": 120.5,
"y": 240
}
},
{
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e",
"assistantOverrides": {
"name": "Booking"
},
"position": {
"x": 420,
"y": 240
}
}
],
"members_overrides": {
"voicemailMessage": "Please leave a message after the tone.",
"variableValues": {
"business_name": "Acme Dental"
}
},
"variable_values": {
"business_name": "Acme Dental",
"business_hours": "Mon-Fri 9am-5pm"
},
"metadata": {
"template_id": 5,
"personality_id": 16,
"tags": [
"dental",
"front-desk"
]
},
"created_at": "2026-07-30T14:22:03+00:00",
"updated_at": "2026-07-30T14:22:03+00:00",
"user": {
"id": 42,
"name": "Jane Cooper",
"email": "[email protected]"
},
"creator": {
"id": 42,
"name": "Jane Cooper",
"email": "[email protected]"
},
"memberCount": 2,
"entryAssistantName": "Reception",
"updatedAt": "2026-07-30T14:22:03+00:00",
"createdAt": "2026-07-30T14:22:03+00:00",
"coreData": {
"id": "e5f6a7b8-1c2d-4e3f-9a8b-7c6d5e4f3a2b"
}
}
}
/squads
201
{
"success": true,
"data": {
"name": "Front desk",
"external_squad_id": "e5f6a7b8-1c2d-4e3f-9a8b-7c6d5e4f3a2b",
"status": "published",
"user_id": 42,
"created_by": 42,
"reseller_id": "f1e2d3c4-b5a6-4978-8901-234567890abc",
"workspace_id": 7,
"members": [
{
"assistantId": "a1b2c3d4-1e2f-4a3b-8c9d-0e1f2a3b4c5d",
"assistantOverrides": {
"name": "Reception",
"firstMessage": "Thanks for calling, how can I help?"
},
"assistantDestinations": [
{
"type": "assistant",
"assistantName": "Booking",
"message": "One moment, transferring you.",
"description": "Caller wants to book an appointment",
"transferMode": "rolling-history",
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e"
}
],
"position": {
"x": 120.5,
"y": 240
}
},
{
"assistantId": "b2c3d4e5-2f3a-4b4c-9d0e-1f2a3b4c5d6e",
"assistantOverrides": {
"name": "Booking"
},
"position": {
"x": 420,
"y": 240
}
}
],
"members_overrides": {
"voicemailMessage": "Please leave a message after the tone.",
"variableValues": {
"business_name": "Acme Dental"
}
},
"variable_values": {
"business_name": "Acme Dental",
"business_hours": "Mon-Fri 9am-5pm"
},
"metadata": {
"template_id": 5,
"personality_id": 16,
"tags": [
"dental",
"front-desk"
]
},
"created_at": "2026-07-30T14:22:03+00:00",
"updated_at": "2026-07-30T14:22:03+00:00",
"user": {
"id": 42,
"name": "Jane Cooper",
"email": "[email protected]"
},
"creator": {
"id": 42,
"name": "Jane Cooper",
"email": "[email protected]"
},
"memberCount": 2,
"entryAssistantName": "Reception",
"updatedAt": "2026-07-30T14:22:03+00:00",
"createdAt": "2026-07-30T14:22:03+00:00",
"coreData": {
"id": "e5f6a7b8-1c2d-4e3f-9a8b-7c6d5e4f3a2b"
}
}
}