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
- Always authenticate before making API calls
- Use environment variables for sensitive data
- Implement proper error handling and timeouts
- Choose appropriate polling intervals based on expected job duration
- Parse responses carefully and handle different output formats
- Log important events for debugging and monitoring
- Implement retry logic for transient failures