Introduction
Master the API with our comprehensive guide covering authentication, service account management, and data querying. Includes production-ready code samples in multiple programming languages.
This guide is structured to help you build applications quickly:
- Complete API Flow - Visual flowchart and step-by-step app building sequence.
- Authentication - JWT-based login and Service Account management.
- Workspaces & Workbooks - Core data operations.
π Base URL and configurationβ
https://be.datagol.aiAll endpoints below are relative to this base URL.
π Complete workflowβ
Step 1: Login
POST /idp/api/v1/user/login β Extract JWT from
Authorization header
Step 2: Create Service Account
Step 3: Access Data
Use service account token as x-auth-token for noCo
endpoints
π οΈ Developer & AI Toolingβ
Leverage these resources to integrate DataGOL APIs into your workflow or allow AI agents to interact with your data.
In Cursor or Claude Code, you can simply point the tool to the downloaded openapi.yaml to help it generate precise API integration code for your project.
π Common headersβ
| Endpoint Type | Required Headers | Example |
|---|---|---|
| All Requests | Content-Type: application/json | Content-Type: application/json |
| IdP Endpoints | Authorization: Bearer <JWT> | Authorization: Bearer eyJhbGciOiJIUzI1NiIs... |
| noCo Endpoints | x-auth-token: <service-token> | x-auth-token: sa_1234567890abcdef... |
β οΈ Security and error handlingβ
π Token Security
- Treat all tokens as secrets - never commit to source control
- Prefer tokens with expiry over non-expiring tokens
- Rotate tokens regularly for enhanced security
π Error Handling
Handle HTTP 401/403 by refreshing JWT or resetting service account token
Use HTTPS only (all endpoints are
https://)- Implement proper error logging and monitoring
π» Code samplesβ
Replace placeholders like YOUR_JWT, YOUR_SERVICE_TOKEN, YOUR_WORKSPACE_ID, and YOUR_TABLE_ID with your actual values.
- React
- Python
- JavaScript
- Go
- C++
import React, { useEffect, useState } from "react";
export default function QueryTable() {
const [rows, setRows] = useState([]);
const [loading, setLoading] = useState(false);
const token = process.env.REACT_APP_SERVICE_TOKEN;
const workspaceId = "YOUR_WORKSPACE_ID";
const tableId = "YOUR_TABLE_ID";
useEffect(() => {
async function run() {
setLoading(true);
try {
const res = await fetch(
`https://be.datagol.ai/noCo/api/v2/workspaces/${workspaceId}/tables/${tableId}/executeQuery`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-auth-token": token,
},
body: JSON.stringify({ value: "SELECT * FROM table_6ec53cc4" }),
},
);
const data = await res.json().catch(() => ({}));
setRows(data.rows || []);
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
}
run();
}, [token, workspaceId, tableId]);
if (loading) return <div>Loadingβ¦</div>;
return (
<table>
<tbody>
{rows.map((r, i) => (
<tr key={i}>
{Object.values(r).map((v, j) => (
<td key={j}>{String(v)}</td>
))}
</tr>
))}
</tbody>
</table>
);
}
import os
import requests
BASE = "https://be.datagol.ai"
# 1) Login (JWT)
login = requests.post(
f"{BASE}/idp/api/v1/user/login",
json={"email": os.environ["EMAIL"], "password": os.environ["PASSWORD"]},
)
jwt = login.headers.get("Authorization", "").replace("Bearer ", "")
# 2) Create service account token
svc = requests.post(
f"{BASE}/idp/api/v1/company/serviceAccount",
headers={"Authorization": f"Bearer {jwt}"},
json={"name": "sales", "description": ""},
)
service_token = svc.json()["token"]
# 3) Execute a query with service token
workspace_id = "YOUR_WORKSPACE_ID"
table_id = "YOUR_TABLE_ID"
q = requests.post(
f"{BASE}/noCo/api/v2/workspaces/{workspace_id}/tables/{table_id}/executeQuery",
headers={"x-auth-token": service_token, "Content-Type": "application/json"},
json={"value": "SELECT * FROM table_6ec53cc4"},
)
print(q.json())
const BASE = "https://be.datagol.ai";
async function login(email, password) {
const res = await fetch(`${BASE}/idp/api/v1/user/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
const auth = res.headers.get("Authorization") || "";
return auth.replace("Bearer ", "");
}
async function createServiceToken(jwt) {
const res = await fetch(`${BASE}/idp/api/v1/company/serviceAccount`, {
method: "POST",
headers: {
Authorization: `Bearer ${jwt}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "sales", description: "" }),
});
const body = await res.json();
return body.token;
}
async function executeQuery(serviceToken, workspaceId, tableId, sql) {
const res = await fetch(
`${BASE}/noCo/api/v2/workspaces/${workspaceId}/tables/${tableId}/executeQuery`,
{
method: "POST",
headers: {
"x-auth-token": serviceToken,
"Content-Type": "application/json",
},
body: JSON.stringify({ value: sql }),
},
);
return res.json();
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
type TokenResp struct { Token string `json:"token"` }
func main() {
base := "https://be.datagol.ai"
loginBody := []byte(`{"email":"YOUR_EMAIL","password":"YOUR_PASSWORD"}`)
req, _ := http.NewRequest("POST", base+"/idp/api/v1/user/login", bytes.NewBuffer(loginBody))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
jwt := strings.TrimPrefix(resp.Header.Get("Authorization"), "Bearer ")
body := []byte(`{"name":"sales","description":""}`)
req2, _ := http.NewRequest("POST", base+"/idp/api/v1/company/serviceAccount", bytes.NewBuffer(body))
req2.Header.Set("Authorization", "Bearer "+jwt)
req2.Header.Set("Content-Type", "application/json")
resp2, _ := http.DefaultClient.Do(req2)
defer resp2.Body.Close()
var tr TokenResp
json.NewDecoder(resp2.Body).Decode(&tr)
workspaceId := "YOUR_WORKSPACE_ID"
tableId := "YOUR_TABLE_ID"
payload := map[string]string{"value": "SELECT * FROM table_6ec53cc4"}
buf, _ := json.Marshal(payload)
req3, _ := http.NewRequest("POST", fmt.Sprintf("%s/noCo/api/v2/workspaces/%s/tables/%s/executeQuery", base, workspaceId, tableId), bytes.NewBuffer(buf))
req3.Header.Set("x-auth-token", tr.Token)
req3.Header.Set("Content-Type", "application/json")
resp3, _ := http.DefaultClient.Do(req3)
defer resp3.Body.Close()
out, _ := io.ReadAll(resp3.Body)
fmt.Println(string(out))
}
#include <curl/curl.h>
#include <iostream>
#include <string>
static size_t WriteCB(void* contents, size_t size, size_t nmemb, void* userp) {
((std::string*)userp)->append((char*)contents, size*nmemb);
return size*nmemb;
}
int main() {
const std::string BASE = "https://be.datagol.ai";
const std::string SERVICE_TOKEN = "YOUR_SERVICE_TOKEN";
const std::string WORKSPACE = "YOUR_WORKSPACE_ID";
const std::string TABLE = "YOUR_TABLE_ID";
CURL* curl = curl_easy_init();
if(!curl) return 1;
std::string url = BASE + "/noCo/api/v2/workspaces/" + WORKSPACE + "/tables/" + TABLE + "/executeQuery";
std::string payload = "{\"value\":\"SELECT * FROM table_6ec53cc4\"}";
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, ("x-auth-token: " + SERVICE_TOKEN).c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str());
std::string response;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCB);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl);
if(res != CURLE_OK) std::cerr << "curl error: " << curl_easy_strerror(res) << "\n";
std::cout << response << std::endl;
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return 0;
}
Was this helpful?