Skip to main content

Code Examples

This guide provides comprehensive code examples for integrating with the Synthreo Builder API across multiple programming languages. Each example demonstrates the complete workflow: authentication, job execution, and status monitoring.

Prerequisites

Before running these examples, ensure you have:

  • Your API credentials (email, password, and user ID)
  • A cognitive diagram ID for execution
  • Node IDs for training operations (if applicable)

Environment Variables:

# .env file
SYNTHREO_API_EMAIL=your-api-key@botx.cloud
SYNTHREO_API_PASSWORD=your-secure-password
SYNTHREO_USER_ID=123
SYNTHREO_DIAGRAM_ID=12345
SYNTHREO_TRAINING_NODE_ID=your-training-node-uuid

Complete Workflow Examples

cURL

Authentication

# Obtain JWT Token
curl -X POST 'https://auth.synthreo.ai/login' \
-H 'Content-Type: application/json' \
-H 'Accept: */*' \
-d '{
"email": "your-api-key@botx.cloud",
"password": "YOUR_PASSWORD",
"userId": 123
}'

Synchronous Execution

# Execute cognitive diagram
curl -X POST 'https://api.botx.cloud/CognitiveDiagram/12345/Execute' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Origin: https://builder.synthreo.ai' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN' \
-d '{
"Action": "Execute",
"UserSays": "[{\"userSays\":\"Hello, how can you help me?\"}]"
}'

Asynchronous Job Execution

# Initiate a long-running job
curl -X POST 'https://api.botx.cloud/CognitiveDiagram/12345/ExecuteAsJob' \
-H 'Content-Type: application/json' \
-H 'Accept: */*' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN' \
-d '{
"Action": "Execute",
"UserSays": "[{\"userSays\":\"start processing\"}]",
"RobotSays": "",
"CallerSource": 1
}'

# Poll job status (use job ID from previous response)
curl -X GET 'https://api.botx.cloud/job/JOB_ID' \
-H 'Accept: */*' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN'

Agent Training

# Trigger training
curl -X PATCH 'https://api.botx.cloud/CognitiveDiagram/8139/TrainNode' \
-H 'Content-Type: application/json' \
-H 'Accept: */*' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN' \
-d '{
"nodeId": "your-training-node-uuid",
"repositoryNodeId": 59,
"finishedFlag": false,
"logText": "Training started by API user"
}'

# Monitor training status
curl -X GET 'https://api.botx.cloud/CognitiveDiagram/8139' \
-H 'Accept: */*' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN'

Python

Complete Implementation

import requests
import time
import os
from typing import Optional, Dict, Any

class SynthreoClient:
def __init__(self, email: str, password: str, user_id: int):
self.email = email
self.password = password
self.user_id = user_id
self.token = None
self.base_url = 'https://api.botx.cloud'
self.auth_url = 'https://auth.synthreo.ai/login'

def authenticate(self) -> str:
"""Obtain JWT token for API authentication"""
payload = {
"email": self.email,
"password": self.password,
"userId": self.user_id
}

headers = {
'Content-Type': 'application/json',
'Accept': '*/*'
}

try:
response = requests.post(self.auth_url, headers=headers, json=payload)
response.raise_for_status()

data = response.json()
self.token = data['token']
print(f'Authentication successful')
return self.token

except requests.exceptions.RequestException as e:
print(f'Authentication failed: {e}')
raise

def get_headers(self) -> Dict[str, str]:
"""Get headers with authorization token"""
if not self.token:
self.authenticate()

return {
'Authorization': f'Bearer {self.token}',
'Content-Type': 'application/json',
'Accept': '*/*'
}

def execute_diagram(self, diagram_id: int, message: str,
conversation_id: Optional[str] = None) -> Dict[str, Any]:
"""Execute cognitive diagram synchronously"""
url = f'{self.base_url}/CognitiveDiagram/{diagram_id}/Execute'

user_says_data = {"userSays": message}
if conversation_id:
user_says_data["conversationId"] = conversation_id

payload = {
"Action": "Execute",
"UserSays": f'[{user_says_data}]'
}

headers = self.get_headers()
headers.update({
'Accept': 'application/json',
'Origin': 'https://builder.synthreo.ai'
})

try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()

except requests.exceptions.RequestException as e:
print(f'Diagram execution failed: {e}')
raise

def execute_as_job(self, diagram_id: int, message: str = "start") -> str:
"""Execute cognitive diagram as asynchronous job"""
url = f'{self.base_url}/CognitiveDiagram/{diagram_id}/ExecuteAsJob'

payload = {
"Action": "Execute",
"UserSays": f'[{{"userSays":"{message}"}}]',
"RobotSays": "",
"CallerSource": 1
}

headers = self.get_headers()

try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()

data = response.json()
job_id = data['job']['id']
print(f'Job initiated with ID: {job_id}')
return job_id

except requests.exceptions.RequestException as e:
print(f'Job initiation failed: {e}')
raise

def poll_job_status(self, job_id: str, interval: int = 30,
timeout: int = 3600) -> Dict[str, Any]:
"""Poll job status until completion"""
url = f'{self.base_url}/job/{job_id}'
headers = self.get_headers()

start_time = time.time()

while True:
if time.time() - start_time > timeout:
raise TimeoutError(f'Job {job_id} timed out after {timeout} seconds')

try:
response = requests.get(url, headers=headers)

if response.status_code == 202:
print('Job is still running...')
time.sleep(interval)
continue

elif response.status_code == 200:
data = response.json()
print('Job completed!')
return data

else:
raise requests.exceptions.HTTPError(
f'Unexpected status code: {response.status_code}'
)

except requests.exceptions.RequestException as e:
print(f'Error polling job status: {e}')
raise

def trigger_training(self, diagram_id: int, node_id: str,
repository_node_id: int = 59) -> Dict[str, Any]:
"""Trigger agent training"""
url = f'{self.base_url}/CognitiveDiagram/{diagram_id}/TrainNode'

payload = {
"nodeId": node_id,
"repositoryNodeId": repository_node_id,
"finishedFlag": False,
"logText": "Training started by API user"
}

headers = self.get_headers()

try:
response = requests.patch(url, headers=headers, json=payload)
response.raise_for_status()

data = response.json()
print(f'Training triggered for agent {diagram_id}')
return data

except requests.exceptions.RequestException as e:
print(f'Training trigger failed: {e}')
raise

def monitor_training(self, diagram_id: int, interval: int = 60,
timeout: int = 3600) -> Dict[str, Any]:
"""Monitor training progress"""
url = f'{self.base_url}/CognitiveDiagram/{diagram_id}'
headers = self.get_headers()

start_time = time.time()

while True:
if time.time() - start_time > timeout:
raise TimeoutError(f'Training timed out after {timeout} seconds')

try:
response = requests.get(url, headers=headers)
response.raise_for_status()

data = response.json()
state_id = data.get('stateId')

if state_id == 6:
print('Agent is training...')
time.sleep(interval)
elif state_id == 2:
print('Training completed! Agent is ready.')
return data
else:
print(f'Unexpected state ID: {state_id}')
return data

except requests.exceptions.RequestException as e:
print(f'Error monitoring training: {e}')
raise

def parse_response(api_response: Dict[str, Any]) -> str:
"""Parse API response to extract meaningful output"""
if api_response.get('outputData'):
try:
import json
output_data = json.loads(api_response['outputData'])

if isinstance(output_data, list) and output_data:
return str(output_data[0])
elif isinstance(output_data, dict):
# Try common response field names
for field in ['response', 'gpt_response', 'answer', 'result']:
if field in output_data:
return str(output_data[field])
return json.dumps(output_data, indent=2)
else:
return str(output_data)
except (json.JSONDecodeError, KeyError):
return api_response['outputData']

if api_response.get('errorData') and api_response['errorData'] != "[]":
import json
try:
errors = json.loads(api_response['errorData'])
return f"Error: {errors[0].get('message', 'Unknown error')}"
except json.JSONDecodeError:
return f"Error: {api_response['errorData']}"

return "No response generated"

# Usage Example
if __name__ == '__main__':
# Initialize client
client = SynthreoClient(
email=os.getenv('SYNTHREO_API_EMAIL'),
password=os.getenv('SYNTHREO_API_PASSWORD'),
user_id=int(os.getenv('SYNTHREO_USER_ID'))
)

diagram_id = int(os.getenv('SYNTHREO_DIAGRAM_ID'))

try:
# Example 1: Synchronous execution
response = client.execute_diagram(diagram_id, "Hello, how are you?")
ai_response = parse_response(response)
print(f"AI Response: {ai_response}")

# Example 2: Asynchronous job execution
job_id = client.execute_as_job(diagram_id, "start processing")
job_result = client.poll_job_status(job_id)
print(f"Job Result: {parse_response(job_result)}")

# Example 3: Training workflow (optional)
training_node_id = os.getenv('SYNTHREO_TRAINING_NODE_ID')
if training_node_id:
client.trigger_training(diagram_id, training_node_id)
client.monitor_training(diagram_id)

except Exception as e:
print(f"Error: {e}")

Node.js

Complete Implementation

const axios = require('axios');

class SynthreoClient {
constructor(email, password, userId) {
this.email = email;
this.password = password;
this.userId = userId;
this.token = null;
this.baseUrl = 'https://api.botx.cloud';
this.authUrl = 'https://auth.synthreo.ai/login';
}

async authenticate() {
const payload = {
email: this.email,
password: this.password,
userId: this.userId
};

const headers = {
'Content-Type': 'application/json',
'Accept': '*/*'
};

try {
const response = await axios.post(this.authUrl, payload, { headers });
this.token = response.data.token;
console.log('Authentication successful');
return this.token;
} catch (error) {
console.error('Authentication failed:', error.response?.data || error.message);
throw error;
}
}

getHeaders() {
if (!this.token) {
throw new Error('Not authenticated. Call authenticate() first.');
}
return {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json',
'Accept': '*/*'
};
}

async executeDiagram(diagramId, message, conversationId = null) {
const url = `${this.baseUrl}/CognitiveDiagram/${diagramId}/Execute`;

const userSaysData = { userSays: message };
if (conversationId) {
userSaysData.conversationId = conversationId;
}

const payload = {
Action: "Execute",
UserSays: JSON.stringify([userSaysData])
};

const headers = {
...this.getHeaders(),
'Accept': 'application/json',
'Origin': 'https://builder.synthreo.ai'
};

try {
const response = await axios.post(url, payload, { headers });
return response.data;
} catch (error) {
console.error('Diagram execution failed:', error.response?.data || error.message);
throw error;
}
}

async executeAsJob(diagramId, message = "start") {
const url = `${this.baseUrl}/CognitiveDiagram/${diagramId}/ExecuteAsJob`;

const payload = {
Action: "Execute",
UserSays: `[{"userSays":"${message}"}]`,
RobotSays: "",
CallerSource: 1
};

const headers = this.getHeaders();

try {
const response = await axios.post(url, payload, { headers });
const jobId = response.data.job.id;
console.log(`Job initiated with ID: ${jobId}`);
return jobId;
} catch (error) {
console.error('Job initiation failed:', error.response?.data || error.message);
throw error;
}
}

async pollJobStatus(jobId, interval = 30000, timeout = 3600000) {
const url = `${this.baseUrl}/job/${jobId}`;
const headers = this.getHeaders();
const startTime = Date.now();

return new Promise((resolve, reject) => {
const poll = async () => {
if (Date.now() - startTime > timeout) {
reject(new Error(`Job ${jobId} timed out after ${timeout/1000} seconds`));
return;
}

try {
const response = await axios.get(url, { headers });

if (response.status === 202) {
console.log('Job is still running...');
setTimeout(poll, interval);
} else if (response.status === 200) {
console.log('Job completed!');
resolve(response.data);
} else {
reject(new Error(`Unexpected status code: ${response.status}`));
}
} catch (error) {
console.error('Error polling job status:', error.response?.data || error.message);
reject(error);
}
};

poll();
});
}

async triggerTraining(diagramId, nodeId, repositoryNodeId = 59) {
const url = `${this.baseUrl}/CognitiveDiagram/${diagramId}/TrainNode`;

const payload = {
nodeId: nodeId,
repositoryNodeId: repositoryNodeId,
finishedFlag: false,
logText: "Training started by API user"
};

const headers = this.getHeaders();

try {
const response = await axios.patch(url, payload, { headers });
console.log(`Training triggered for agent ${diagramId}`);
return response.data;
} catch (error) {
console.error('Training trigger failed:', error.response?.data || error.message);
throw error;
}
}

async monitorTraining(diagramId, interval = 60000, timeout = 3600000) {
const url = `${this.baseUrl}/CognitiveDiagram/${diagramId}`;
const headers = this.getHeaders();
const startTime = Date.now();

return new Promise((resolve, reject) => {
const monitor = async () => {
if (Date.now() - startTime > timeout) {
reject(new Error(`Training timed out after ${timeout/1000} seconds`));
return;
}

try {
const response = await axios.get(url, { headers });
const stateId = response.data.stateId;

if (stateId === 6) {
console.log('Agent is training...');
setTimeout(monitor, interval);
} else if (stateId === 2) {
console.log('Training completed! Agent is ready.');
resolve(response.data);
} else {
console.log(`Unexpected state ID: ${stateId}`);
resolve(response.data);
}
} catch (error) {
console.error('Error monitoring training:', error.response?.data || error.message);
reject(error);
}
};

monitor();
});
}
}

function parseResponse(apiResponse) {
if (apiResponse.outputData) {
try {
const outputData = JSON.parse(apiResponse.outputData);

if (Array.isArray(outputData) && outputData.length > 0) {
return String(outputData[0]);
} else if (typeof outputData === 'object' && outputData !== null) {
// Try common response field names
const commonFields = ['response', 'gpt_response', 'answer', 'result'];
for (const field of commonFields) {
if (outputData[field]) {
return String(outputData[field]);
}
}
return JSON.stringify(outputData, null, 2);
} else {
return String(outputData);
}
} catch (e) {
return apiResponse.outputData;
}
}

if (apiResponse.errorData && apiResponse.errorData !== "[]") {
try {
const errors = JSON.parse(apiResponse.errorData);
return `Error: ${errors[0]?.message || 'Unknown error'}`;
} catch (e) {
return `Error: ${apiResponse.errorData}`;
}
}

return "No response generated";
}

// Usage Example
async function main() {
const client = new SynthreoClient(
process.env.SYNTHREO_API_EMAIL,
process.env.SYNTHREO_API_PASSWORD,
parseInt(process.env.SYNTHREO_USER_ID)
);

const diagramId = parseInt(process.env.SYNTHREO_DIAGRAM_ID);

try {
// Authenticate
await client.authenticate();

// Example 1: Synchronous execution
const response = await client.executeDiagram(diagramId, "Hello, how are you?");
const aiResponse = parseResponse(response);
console.log(`AI Response: ${aiResponse}`);

// Example 2: Asynchronous job execution
const jobId = await client.executeAsJob(diagramId, "start processing");
const jobResult = await client.pollJobStatus(jobId);
console.log(`Job Result: ${parseResponse(jobResult)}`);

// Example 3: Training workflow (optional)
const trainingNodeId = process.env.SYNTHREO_TRAINING_NODE_ID;
if (trainingNodeId) {
await client.triggerTraining(diagramId, trainingNodeId);
await client.monitorTraining(diagramId);
}

} catch (error) {
console.error('Error:', error.message);
}
}

// Run if this file is executed directly
if (require.main === module) {
main();
}

module.exports = { SynthreoClient, parseResponse };

Java

Complete Implementation

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class SynthreoClient {
private static final String BASE_URL = "https://api.botx.cloud";
private static final String AUTH_URL = "https://auth.synthreo.ai/login";

private final String email;
private final String password;
private final int userId;
private String token;
private final ObjectMapper objectMapper;

public SynthreoClient(String email, String password, int userId) {
this.email = email;
this.password = password;
this.userId = userId;
this.objectMapper = new ObjectMapper();
}

public String authenticate() throws Exception {
String jsonPayload = String.format(
"{\"email\":\"%s\",\"password\":\"%s\",\"userId\":%d}",
email, password, userId
);

HttpURLConnection connection = createConnection(AUTH_URL, "POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "*/*");

try (OutputStream os = connection.getOutputStream()) {
os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
}

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
String response = readResponse(connection);
JsonNode jsonResponse = objectMapper.readTree(response);
this.token = jsonResponse.get("token").asText();
System.out.println("Authentication successful");
return this.token;
} else {
throw new RuntimeException("Authentication failed with code: " + responseCode);
}
}

public String executeDiagram(int diagramId, String message) throws Exception {
return executeDiagram(diagramId, message, null);
}

public String executeDiagram(int diagramId, String message, String conversationId) throws Exception {
String url = BASE_URL + "/CognitiveDiagram/" + diagramId + "/Execute";

String userSaysData = conversationId != null
? String.format("{\"userSays\":\"%s\",\"conversationId\":\"%s\"}", message, conversationId)
: String.format("{\"userSays\":\"%s\"}", message);

String jsonPayload = String.format(
"{\"Action\":\"Execute\",\"UserSays\":\"[%s]\"}",
userSaysData.replace("\"", "\\\"")
);

HttpURLConnection connection = createConnection(url, "POST");
addAuthHeaders(connection);
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Origin", "https://builder.synthreo.ai");

try (OutputStream os = connection.getOutputStream()) {
os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
}

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
return readResponse(connection);
} else {
throw new RuntimeException("Diagram execution failed with code: " + responseCode);
}
}

public String executeAsJob(int diagramId, String message) throws Exception {
String url = BASE_URL + "/CognitiveDiagram/" + diagramId + "/ExecuteAsJob";

String jsonPayload = String.format(
"{\"Action\":\"Execute\",\"UserSays\":\"[{\\\"userSays\\\":\\\"%s\\\"}]\",\"RobotSays\":\"\",\"CallerSource\":1}",
message
);

HttpURLConnection connection = createConnection(url, "POST");
addAuthHeaders(connection);

try (OutputStream os = connection.getOutputStream()) {
os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
}

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
String response = readResponse(connection);
JsonNode jsonResponse = objectMapper.readTree(response);
String jobId = jsonResponse.get("job").get("id").asText();
System.out.println("Job initiated with ID: " + jobId);
return jobId;
} else {
throw new RuntimeException("Job initiation failed with code: " + responseCode);
}
}

public String pollJobStatus(String jobId, int intervalSeconds, int timeoutSeconds) throws Exception {
String url = BASE_URL + "/job/" + jobId;
long startTime = System.currentTimeMillis();
long timeoutMs = timeoutSeconds * 1000L;

while (System.currentTimeMillis() - startTime < timeoutMs) {
HttpURLConnection connection = createConnection(url, "GET");
addAuthHeaders(connection);

int responseCode = connection.getResponseCode();

if (responseCode == 202) {
System.out.println("Job is still running...");
TimeUnit.SECONDS.sleep(intervalSeconds);
continue;
} else if (responseCode == 200) {
System.out.println("Job completed!");
return readResponse(connection);
} else {
throw new RuntimeException("Unexpected response code: " + responseCode);
}
}

throw new RuntimeException("Job polling timed out after " + timeoutSeconds + " seconds");
}

public String triggerTraining(int diagramId, String nodeId, int repositoryNodeId) throws Exception {
String url = BASE_URL + "/CognitiveDiagram/" + diagramId + "/TrainNode";

String jsonPayload = String.format(
"{\"nodeId\":\"%s\",\"repositoryNodeId\":%d,\"finishedFlag\":false,\"logText\":\"Training started by API user\"}",
nodeId, repositoryNodeId
);

HttpURLConnection connection = createConnection(url, "PATCH");
addAuthHeaders(connection);

try (OutputStream os = connection.getOutputStream()) {
os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
}

int responseCode = connection.getResponseCode();
if (responseCode == 200 || responseCode == 204) {
System.out.println("Training triggered for agent " + diagramId);
return responseCode == 200 ? readResponse(connection) : "Training initiated";
} else {
throw new RuntimeException("Training trigger failed with code: " + responseCode);
}
}

public String monitorTraining(int diagramId, int intervalSeconds, int timeoutSeconds) throws Exception {
String url = BASE_URL + "/CognitiveDiagram/" + diagramId;
long startTime = System.currentTimeMillis();
long timeoutMs = timeoutSeconds * 1000L;

while (System.currentTimeMillis() - startTime < timeoutMs) {
HttpURLConnection connection = createConnection(url, "GET");
addAuthHeaders(connection);

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
String response = readResponse(connection);
JsonNode jsonResponse = objectMapper.readTree(response);
int stateId = jsonResponse.get("stateId").asInt();

if (stateId == 6) {
System.out.println("Agent is training...");
TimeUnit.SECONDS.sleep(intervalSeconds);
} else if (stateId == 2) {
System.out.println("Training completed! Agent is ready.");
return response;
} else {
System.out.println("Unexpected state ID: " + stateId);
return response;
}
} else {
throw new RuntimeException("Training monitoring failed with code: " + responseCode);
}
}

throw new RuntimeException("Training monitoring timed out after " + timeoutSeconds + " seconds");
}

public static String parseResponse(String apiResponse) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonResponse = mapper.readTree(apiResponse);

JsonNode outputData = jsonResponse.get("outputData");
if (outputData != null && !outputData.isNull()) {
String outputDataStr = outputData.asText();

try {
JsonNode parsedOutput = mapper.readTree(outputDataStr);

if (parsedOutput.isArray() && parsedOutput.size() > 0) {
return parsedOutput.get(0).asText();
} else if (parsedOutput.isObject()) {
// Try common response field names
String[] fields = {"response", "gpt_response", "answer", "result"};
for (String field : fields) {
if (parsedOutput.has(field)) {
return parsedOutput.get(field).asText();
}
}
return parsedOutput.toString();
} else {
return parsedOutput.asText();
}
} catch (Exception e) {
return outputDataStr;
}
}

JsonNode errorData = jsonResponse.get("errorData");
if (errorData != null && !errorData.isNull() && !errorData.asText().equals("[]")) {
try {
JsonNode errors = mapper.readTree(errorData.asText());
if (errors.isArray() && errors.size() > 0) {
return "Error: " + errors.get(0).get("message").asText();
}
} catch (Exception e) {
return "Error: " + errorData.asText();
}
}

return "No response generated";

} catch (Exception e) {
return "Failed to parse response: " + e.getMessage();
}
}

private HttpURLConnection createConnection(String urlString, String method) throws Exception {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(method);
connection.setDoOutput(true);
return connection;
}

private void addAuthHeaders(HttpURLConnection connection) {
if (token == null) {
throw new RuntimeException("Not authenticated. Call authenticate() first.");
}
connection.setRequestProperty("Authorization", "Bearer " + token);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "*/*");
}

private String readResponse(HttpURLConnection connection) throws Exception {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
}
}

// Usage Example
public static void main(String[] args) {
try {
// Initialize client with environment variables
String email = System.getenv("SYNTHREO_API_EMAIL");
String password = System.getenv("SYNTHREO_API_PASSWORD");
int userId = Integer.parseInt(System.getenv("SYNTHREO_USER_ID"));
int diagramId = Integer.parseInt(System.getenv("SYNTHREO_DIAGRAM_ID"));

SynthreoClient client = new SynthreoClient(email, password, userId);

// Authenticate
client.authenticate();

// Example 1: Synchronous execution
String response = client.executeDiagram(diagramId, "Hello, how are you?");
String aiResponse = parseResponse(response);
System.out.println("AI Response: " + aiResponse);

// Example 2: Asynchronous job execution
String jobId = client.executeAsJob(diagramId, "start processing");
String jobResult = client.pollJobStatus(jobId, 30, 3600);
System.out.println("Job Result: " + parseResponse(jobResult));

// Example 3: Training workflow (optional)
String trainingNodeId = System.getenv("SYNTHREO_TRAINING_NODE_ID");
if (trainingNodeId != null && !trainingNodeId.isEmpty()) {
client.triggerTraining(diagramId, trainingNodeId, 59);
client.monitorTraining(diagramId, 60, 3600);
}

} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}

C# (.NET)

Complete Implementation

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Threading;

public class SynthreoClient
{
private readonly string _email;
private readonly string _password;
private readonly int _userId;
private string _token;
private readonly HttpClient _httpClient;
private const string BaseUrl = "https://api.botx.cloud";
private const string AuthUrl = "https://auth.synthreo.ai/login";

public SynthreoClient(string email, string password, int userId)
{
_email = email;
_password = password;
_userId = userId;
_httpClient = new HttpClient();
}

public async Task<string> AuthenticateAsync()
{
var payload = new
{
email = _email,
password = _password,
userId = _userId
};

var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");

try
{
var response = await _httpClient.PostAsync(AuthUrl, content);
response.EnsureSuccessStatusCode();

var responseBody = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(responseBody);

_token = doc.RootElement.GetProperty("token").GetString();
Console.WriteLine("Authentication successful");
return _token;
}
catch (HttpRequestException ex)
{
throw new Exception($"Authentication failed: {ex.Message}");
}
}

private void SetAuthHeaders()
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Not authenticated. Call AuthenticateAsync() first.");
}

_httpClient.DefaultRequestHeaders.Clear();
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _token);
_httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("*/*"));
}

public async Task<string> ExecuteDiagramAsync(int diagramId, string message,
string conversationId = null)
{
SetAuthHeaders();
var url = $"{BaseUrl}/CognitiveDiagram/{diagramId}/Execute";

var userSaysData = new { userSays = message };
var userSaysJson = conversationId != null
? JsonSerializer.Serialize(new { userSays = message, conversationId })
: JsonSerializer.Serialize(userSaysData);

var payload = new
{
Action = "Execute",
UserSays = $"[{userSaysJson}]"
};

var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");

// Add specific headers for diagram execution
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/json");

var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Add("Origin", "https://builder.synthreo.ai");

try
{
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
throw new Exception($"Diagram execution failed: {ex.Message}");
}
}

public async Task<string> ExecuteAsJobAsync(int diagramId, string message = "start")
{
SetAuthHeaders();
var url = $"{BaseUrl}/CognitiveDiagram/{diagramId}/ExecuteAsJob";

var payload = new
{
Action = "Execute",
UserSays = $"[{{\"userSays\":\"{message}\"}}]",
RobotSays = "",
CallerSource = 1
};

var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");

try
{
var response = await _httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();

var responseBody = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(responseBody);

var jobId = doc.RootElement.GetProperty("job").GetProperty("id").GetString();
Console.WriteLine($"Job initiated with ID: {jobId}");
return jobId;
}
catch (HttpRequestException ex)
{
throw new Exception($"Job initiation failed: {ex.Message}");
}
}

public async Task<string> PollJobStatusAsync(string jobId, int intervalSeconds = 30,
int timeoutSeconds = 3600)
{
SetAuthHeaders();
var url = $"{BaseUrl}/job/{jobId}";
var startTime = DateTime.UtcNow;
var timeout = TimeSpan.FromSeconds(timeoutSeconds);

while (DateTime.UtcNow - startTime < timeout)
{
try
{
var response = await _httpClient.GetAsync(url);

if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
{
Console.WriteLine("Job is still running...");
await Task.Delay(TimeSpan.FromSeconds(intervalSeconds));
continue;
}
else if (response.IsSuccessStatusCode)
{
Console.WriteLine("Job completed!");
return await response.Content.ReadAsStringAsync();
}
else
{
throw new Exception($"Unexpected status code: {response.StatusCode}");
}
}
catch (HttpRequestException ex)
{
throw new Exception($"Error polling job status: {ex.Message}");
}
}

throw new TimeoutException($"Job {jobId} timed out after {timeoutSeconds} seconds");
}

public async Task<string> TriggerTrainingAsync(int diagramId, string nodeId,
int repositoryNodeId = 59)
{
SetAuthHeaders();
var url = $"{BaseUrl}/CognitiveDiagram/{diagramId}/TrainNode";

var payload = new
{
nodeId = nodeId,
repositoryNodeId = repositoryNodeId,
finishedFlag = false,
logText = "Training started by API user"
};

var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");

try
{
var response = await _httpClient.PatchAsync(url, content);
response.EnsureSuccessStatusCode();

Console.WriteLine($"Training triggered for agent {diagramId}");
return await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
throw new Exception($"Training trigger failed: {ex.Message}");
}
}

public async Task<string> MonitorTrainingAsync(int diagramId, int intervalSeconds = 60,
int timeoutSeconds = 3600)
{
SetAuthHeaders();
var url = $"{BaseUrl}/CognitiveDiagram/{diagramId}";
var startTime = DateTime.UtcNow;
var timeout = TimeSpan.FromSeconds(timeoutSeconds);

while (DateTime.UtcNow - startTime < timeout)
{
try
{
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();

var responseBody = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(responseBody);

var stateId = doc.RootElement.GetProperty("stateId").GetInt32();

if (stateId == 6)
{
Console.WriteLine("Agent is training...");
await Task.Delay(TimeSpan.FromSeconds(intervalSeconds));
}
else if (stateId == 2)
{
Console.WriteLine("Training completed! Agent is ready.");
return responseBody;
}
else
{
Console.WriteLine($"Unexpected state ID: {stateId}");
return responseBody;
}
}
catch (HttpRequestException ex)
{
throw new Exception($"Error monitoring training: {ex.Message}");
}
}

throw new TimeoutException($"Training monitoring timed out after {timeoutSeconds} seconds");
}

public static string ParseResponse(string apiResponse)
{
try
{
using var doc = JsonDocument.Parse(apiResponse);
var root = doc.RootElement;

if (root.TryGetProperty("outputData", out var outputDataElement) &&
!outputDataElement.ValueEquals(""))
{
var outputDataStr = outputDataElement.GetString();

try
{
using var outputDoc = JsonDocument.Parse(outputDataStr);
var outputRoot = outputDoc.RootElement;

if (outputRoot.ValueKind == JsonValueKind.Array && outputRoot.GetArrayLength() > 0)
{
return outputRoot[0].ToString();
}
else if (outputRoot.ValueKind == JsonValueKind.Object)
{
// Try common response field names
var fields = new[] { "response", "gpt_response", "answer", "result" };
foreach (var field in fields)
{
if (outputRoot.TryGetProperty(field, out var fieldElement))
{
return fieldElement.GetString();
}
}
return outputRoot.ToString();
}
else
{
return outputRoot.ToString();
}
}
catch
{
return outputDataStr;
}
}

if (root.TryGetProperty("errorData", out var errorDataElement) &&
!errorDataElement.ValueEquals("[]"))
{
var errorDataStr = errorDataElement.GetString();
try
{
using var errorDoc = JsonDocument.Parse(errorDataStr);
var errorRoot = errorDoc.RootElement;

if (errorRoot.ValueKind == JsonValueKind.Array && errorRoot.GetArrayLength() > 0)
{
var firstError = errorRoot[0];
if (firstError.TryGetProperty("message", out var messageElement))
{
return $"Error: {messageElement.GetString()}";
}
}
}
catch
{
return $"Error: {errorDataStr}";
}
}

return "No response generated";
}
catch (Exception ex)
{
return $"Failed to parse response: {ex.Message}";
}
}

public void Dispose()
{
_httpClient?.Dispose();
}
}

// Usage Example
public class Program
{
public static async Task Main(string[] args)
{
try
{
// Initialize client with environment variables
var email = Environment.GetEnvironmentVariable("SYNTHREO_API_EMAIL");
var password = Environment.GetEnvironmentVariable("SYNTHREO_API_PASSWORD");
var userId = int.Parse(Environment.GetEnvironmentVariable("SYNTHREO_USER_ID"));
var diagramId = int.Parse(Environment.GetEnvironmentVariable("SYNTHREO_DIAGRAM_ID"));

using var client = new SynthreoClient(email, password, userId);

// Authenticate
await client.AuthenticateAsync();

// Example 1: Synchronous execution
var response = await client.ExecuteDiagramAsync(diagramId, "Hello, how are you?");
var aiResponse = SynthreoClient.ParseResponse(response);
Console.WriteLine($"AI Response: {aiResponse}");

// Example 2: Asynchronous job execution
var jobId = await client.ExecuteAsJobAsync(diagramId, "start processing");
var jobResult = await client.PollJobStatusAsync(jobId);
Console.WriteLine($"Job Result: {SynthreoClient.ParseResponse(jobResult)}");

// Example 3: Training workflow (optional)
var trainingNodeId = Environment.GetEnvironmentVariable("SYNTHREO_TRAINING_NODE_ID");
if (!string.IsNullOrEmpty(trainingNodeId))
{
await client.TriggerTrainingAsync(diagramId, trainingNodeId);
await client.MonitorTrainingAsync(diagramId);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}

Quick Start Examples

Simple Synchronous Execution

Python

from synthreo_client import SynthreoClient
import os

client = SynthreoClient(
os.getenv('SYNTHREO_API_EMAIL'),
os.getenv('SYNTHREO_API_PASSWORD'),
int(os.getenv('SYNTHREO_USER_ID'))
)

# Send a simple message
response = client.execute_diagram(12345, "Hello AI!")
print(parse_response(response))

Node.js

const client = new SynthreoClient(
process.env.SYNTHREO_API_EMAIL,
process.env.SYNTHREO_API_PASSWORD,
parseInt(process.env.SYNTHREO_USER_ID)
);

async function quickStart() {
await client.authenticate();
const response = await client.executeDiagram(12345, "Hello AI!");
console.log(parseResponse(response));
}

quickStart();

Asynchronous Job with Polling

Python

# Start a long-running job
job_id = client.execute_as_job(12345, "process data")

# Poll until completion (30-second intervals, 1-hour timeout)
result = client.poll_job_status(job_id, interval=30, timeout=3600)
print(f"Final result: {parse_response(result)}")

Node.js

// Start job and wait for completion
const jobId = await client.executeAsJob(12345, "process data");
const result = await client.pollJobStatus(jobId, 30000, 3600000);
console.log(`Final result: ${parseResponse(result)}`);

Error Handling Examples

Python Error Handling

try:
response = client.execute_diagram(diagram_id, message)
result = parse_response(response)

if result.startswith("Error:"):
print(f"AI Agent Error: {result}")
else:
print(f"Success: {result}")

except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
except Exception as e:
print(f"Unexpected Error: {e}")

Node.js Error Handling

try {
const response = await client.executeDiagram(diagramId, message);
const result = parseResponse(response);

if (result.startsWith("Error:")) {
console.error(`AI Agent Error: ${result}`);
} else {
console.log(`Success: ${result}`);
}
} catch (error) {
if (error.response) {
console.error(`HTTP Error ${error.response.status}: ${error.response.data}`);
} else if (error.request) {
console.error('Network Error: No response received');
} else {
console.error(`Error: ${error.message}`);
}
}

Environment Setup

Python Requirements

# requirements.txt
requests>=2.25.0
python-dotenv>=0.19.0

Node.js Dependencies

{
"dependencies": {
"axios": "^1.6.0",
"dotenv": "^16.3.0"
}
}

Java Dependencies (Maven)

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>

C# Dependencies

<PackageReference Include="System.Text.Json" Version="7.0.0" />

Best Practices

  1. Always authenticate before making API calls
  2. Use environment variables for sensitive data
  3. Implement proper error handling and timeouts
  4. Choose appropriate polling intervals based on expected job duration
  5. Parse responses carefully and handle different output formats
  6. Log important events for debugging and monitoring
  7. Implement retry logic for transient failures