DGIAPI Documentation

Getting Started

This guide will walk you through setting up your first API integration with DGI.

Prerequisites

Before you begin, make sure you have:

  • A DGI account (Sign up here)
  • Your API key from your Profile
  • Node.js 18+ or a modern browser with fetch API support

Step-by-Step Guide

Step 1: Create a Session

The first step is to create a new session using the /v2/session/new endpoint:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Your API key from the profile
const API_KEY = "<YOUR_API_KEY>";
const BASE_URL = "https://api.dgintel.ai";

// Create a new session
async function createSession() {
  try {
    const response = await fetch(`${BASE_URL}/v2/session/new`, {
      method: "POST",
      headers: {
        "accept": "application/json",
        "Authorization": `Bearer ${API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({})
    });

    if (response.ok) {
      const sessionData = await response.json();
      console.log("Session created successfully!");
      console.log(JSON.stringify(sessionData, null, 2));
      return sessionData;
    } else {
      console.error(`Error: ${response.status}`);
      const error = await response.json();
      console.error(error);
    }
  } catch (error) {
    console.error("Network error:", error);
  }
}

// Call the function
createSession();

Response (200 - Successful Response):

text
1
2
3
4
5
6
{
  "session_id": "sess_abc123",
  "status": "active",
  "created_at": "2025-09-10T12:00:00Z"
}

Step 2: Create a Task

Once you have a session, create a new task using the /v2/{chat_session_id}/task/new endpoint:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Assuming you got the session_id from Step 1
const sessionId = "sess_abc123"; // Replace with your actual session_id

// Create a new task
async function createTask(sessionId) {
  const taskData = {
    question: "Analyze the sales data and show trends",
    resume_from_checkpoint_id: "1f02a823-e208-6a11-800f-0e74e6ec030a" // Optional
  };

  try {
    const response = await fetch(`${BASE_URL}/v2/${sessionId}/task/new`, {
      method: "POST",
      headers: {
        "accept": "application/json",
        "Authorization": `Bearer ${API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(taskData)
    });

    if (response.ok) {
      const taskId = await response.json();
      console.log(`Task created successfully! Task ID: ${taskId}`);
      return taskId;
    } else {
      console.error(`Error: ${response.status}`);
      const error = await response.json();
      console.error(error);
    }
  } catch (error) {
    console.error("Network error:", error);
  }
}

// Call the function
createTask(sessionId);

Parameters:

  • chat_session_id (required): The session ID from Step 1
  • question (required): The task or question you want DG-i™ to process
  • resume_from_checkpoint_id (optional): Resume from a previous checkpoint

Response (200 - Successful Response):

text
1
2
"task_abc123"

Response (422 - Validation Error):

text
1
2
3
4
5
6
7
8
9
10
{
  "detail": [
    {
      "loc": ["string", 0],
      "msg": "string", 
      "type": "string"
    }
  ]
}

Step 3: Get Task Messages (Polling)

⚠️ Critical: Polling Required

DG-i™ tasks run asynchronously. You MUST poll the messages endpoint continuously using timestamps to:

  1. Get real-time updates as the AI agent works
  2. Retrieve new messages only (using the timestamp from the last message)
  3. Continue polling until status changes from in_progress to completed

Without proper polling, you'll miss important task updates and results!

Task Status Values:

  • in_progress - Task is still running (keep polling)
  • completed - Task finished successfully (stop polling)
  • interrupted - Task was interrupted (stop polling)

Simple Polling Implementation:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const taskId = "task_abc123"; // From Step 2

async function pollTaskMessages(taskId) {
  let lastTimestamp = null;
  
  while (true) {
    try {
      // Build URL with timestamp to get only new messages
      let url = `${BASE_URL}/v2/tasks/${taskId}/messages`;
      if (lastTimestamp) {
        url += `?timestamp=${encodeURIComponent(lastTimestamp)}`;
      }
      
      const response = await fetch(url, {
        headers: {
          "Authorization": `Bearer ${API_KEY}`,
          "Accept": "application/json"
        }
      });
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      
      const data = await response.json();
      
      // Process new messages
      if (data.messages && data.messages.length > 0) {
        data.messages.forEach(msg => {
          console.log(`[${msg.timestamp}] ${msg.msg}`);
          // Update timestamp to get only newer messages next time
          lastTimestamp = msg.timestamp;
        });
      }
      
      // Check task status
      if (data.task_status === "completed") {
        console.log("✅ Task completed!");
        return data; // Exit polling
      } else if (data.task_status === "interrupted") {
        console.log("⚠️ Task interrupted");
        return data; // Exit polling
      }
      
      // Task still in_progress, wait 100ms and poll again
      await new Promise(resolve => setTimeout(resolve, 100));
      
    } catch (error) {
      console.error("Error:", error);
      // Wait a bit longer on errors before retrying
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
}

// Start polling
pollTaskMessages(taskId);

Production-Ready Implementation with Retries:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
async function pollTaskWithRetries(taskId, options = {}) {
  const {
    maxRetries = 10,
    pollingInterval = 100, // 100ms for real-time updates
    onMessage = (msg) => console.log(msg.msg),
    onStatusChange = (status) => console.log(`Status: ${status}`)
  } = options;
  
  let lastTimestamp = null;
  let retryCount = 0;
  
  while (true) {
    try {
      let url = `${BASE_URL}/v2/tasks/${taskId}/messages`;
      if (lastTimestamp) {
        url += `?timestamp=${encodeURIComponent(lastTimestamp)}`;
      }
      
      const response = await fetch(url, {
        headers: {
          "Authorization": `Bearer ${API_KEY}`,
          "Accept": "application/json"
        }
      });
      
      if (!response.ok) {
        // Server errors - retry with backoff
        if (response.status >= 500 && retryCount < maxRetries) {
          retryCount++;
          const backoff = Math.min(1000 * Math.pow(2, retryCount - 1), 5000);
          console.log(`Server error, retrying in ${backoff}ms...`);
          await new Promise(resolve => setTimeout(resolve, backoff));
          continue;
        }
        throw new Error(`HTTP ${response.status}`);
      }
      
      const data = await response.json();
      retryCount = 0; // Reset on successful response
      
      // Notify status changes
      if (onStatusChange) onStatusChange(data.task_status);
      
      // Process new messages
      if (data.messages && data.messages.length > 0) {
        data.messages.forEach(msg => {
          onMessage(msg);
          lastTimestamp = msg.timestamp;
        });
      }
      
      // Check completion
      if (data.task_status === "completed" || data.task_status === "interrupted") {
        return data;
      }
      
      // Continue polling
      await new Promise(resolve => setTimeout(resolve, pollingInterval));
      
    } catch (error) {
      if (retryCount >= maxRetries) {
        throw error;
      }
      retryCount++;
      const backoff = Math.min(1000 * Math.pow(2, retryCount - 1), 5000);
      console.error(`Error: ${error.message}, retrying in ${backoff}ms...`);
      await new Promise(resolve => setTimeout(resolve, backoff));
    }
  }
}

// Usage
pollTaskWithRetries(taskId, {
  onMessage: (msg) => {
    console.log(`💬 ${msg.msg}`);
    // Handle stream URLs if present
    if (msg.stream_url) {
      console.log(`🖥️ Computer use stream: ${msg.stream_url}`);
    }
  },
  onStatusChange: (status) => {
    console.log(`📊 Status: ${status}`);
  }
}).then(result => {
  console.log("✅ Task finished!", result);
}).catch(error => {
  console.error("❌ Failed:", error);
});

Parameters:

  • task_id (required): The task ID from Step 2
  • timestamp (optional): Filter messages created after this timestamp (ISO 8601 format)

Key Implementation Notes:

  • 🔄 Use timestamps: Always pass the last message's timestamp to get only NEW messages
  • ⏱️ Fast polling: Poll every 100ms for real-time updates
  • 🔧 Handle errors: Implement exponential backoff for server errors (500, 503)
  • 📊 Track status: Monitor in_progresscompleted or interrupted
  • 💾 Stream URLs: Messages may contain stream_url to showcase computer use
  • 🌐 CORS: If calling from browser, you may need to proxy through your backend

Response Examples:

Initial poll (no timestamp):

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "task_status": "in_progress",
  "messages": [
    {
      "msg": "Starting data analysis...",
      "timestamp": "2025-09-10T14:16:13.238Z",
      "stream_url": null
    },
    {
      "msg": "Loading sales data from database...",
      "timestamp": "2025-09-10T14:16:13.339Z",
      "stream_url": null
    }
  ]
}

Subsequent polls (with timestamp - only new messages):

text
1
2
3
4
5
6
7
8
9
10
11
{
  "task_status": "in_progress",
  "messages": [
    {
      "msg": "Processing Q3 revenue trends...",
      "timestamp": "2025-09-10T14:16:13.445Z",
      "stream_url": "https://stream.dgintel.ai/computer_use_xyz789"
    }
  ]
}

Final poll (task completed):

text
1
2
3
4
5
6
7
8
9
10
11
{
  "task_status": "completed",
  "messages": [
    {
      "msg": "Analysis complete. Generated 3 charts and 2 summary reports.",
      "timestamp": "2025-09-10T14:16:14.892Z",
      "stream_url": null
    }
  ]
}

Response (422 - Validation Error):

text
1
2
3
4
5
6
7
8
9
10
{
  "detail": [
    {
      "loc": ["string", 0],
      "msg": "string",
      "type": "string"
    }
  ]
}

Step 4: Verify Your Setup

Test your API connection with the hello endpoint:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Test the connection
async function verifyConnection() {
  try {
    const response = await fetch(`${BASE_URL}/v2/hello`, {
      method: "GET",
      headers: {
        "accept": "application/json",
        "Authorization": `Bearer ${API_KEY}`
      }
    });

    if (response.ok) {
      const data = await response.json();
      console.log("API connection successful!");
      console.log(data);
      return data;
    } else {
      console.error(`Error: ${response.status}`);
    }
  } catch (error) {
    console.error("Network error:", error);
  }
}

// Call the function
verifyConnection();

Complete Example

Here's a complete example that ties everything together:

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Configuration
const API_KEY = "<YOUR_API_KEY>";
const BASE_URL = "https://api.dgintel.ai";

// Main workflow
async function runDGIWorkflow() {
  try {
    // Step 1: Create a session
    const sessionResponse = await fetch(`${BASE_URL}/v2/session/new`, {
      method: "POST",
      headers: {
        "accept": "application/json",
        "Authorization": `Bearer ${API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({})
    });
    
    if (!sessionResponse.ok) throw new Error(`Session creation failed: ${sessionResponse.status}`);
    const sessionData = await sessionResponse.json();
    console.log("✅ Session created:", sessionData.session_id);
    
    // Step 2: Create a task
    const taskResponse = await fetch(`${BASE_URL}/v2/${sessionData.session_id}/task/new`, {
      method: "POST",
      headers: {
        "accept": "application/json",
        "Authorization": `Bearer ${API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        question: "Analyze the sales data and show trends"
      })
    });
    
    if (!taskResponse.ok) throw new Error(`Task creation failed: ${taskResponse.status}`);
    const taskId = await taskResponse.json();
    console.log("✅ Task created:", taskId);
    
    // Step 3: Poll task messages until completion
    console.log("⏳ Polling for task completion...");
    let lastTimestamp = null;
    
    while (true) {
      let url = `${BASE_URL}/v2/tasks/${taskId}/messages`;
      if (lastTimestamp) {
        url += `?timestamp=${encodeURIComponent(lastTimestamp)}`;
      }
      
      const messagesResponse = await fetch(url, {
        headers: {
          "Authorization": `Bearer ${API_KEY}`,
          "Accept": "application/json"
        }
      });
      
      if (!messagesResponse.ok) throw new Error(`HTTP ${messagesResponse.status}`);
      const taskData = await messagesResponse.json();
      
      // Process new messages
      if (taskData.messages && taskData.messages.length > 0) {
        taskData.messages.forEach(msg => {
          console.log(`💬 ${msg.msg}`);
          lastTimestamp = msg.timestamp;
        });
      }
      
      // Check completion
      if (taskData.task_status === "completed") {
        console.log("✅ Task completed!");
        return { sessionData, taskId, taskData };
      } else if (taskData.task_status === "interrupted") {
        console.log("⚠️ Task interrupted");
        return { sessionData, taskId, taskData };
      }
      
      // Continue polling after 100ms
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    
  } catch (error) {
    console.error("❌ Error:", error.message);
  }
}

// Run the workflow
runDGIWorkflow();

Next Steps