Skip to main content

Ingest Data

Send a single time-series data point to a bucket.

Endpoint

POST /api/data

Authentication

API Key (header: X-API-Key)

Requires data:write permission.

Request

Headers

HeaderTypeRequiredDescription
X-API-Keystring✅ YesYour organization API key
Content-Typestring✅ YesMust be application/json

Body Parameters

ParameterTypeRequiredDescription
bucketIdstring✅ YesMongoDB ObjectId of the bucket
dataSourceIdstring✅ YesMongoDB ObjectId of the data source
timestampstring❌ NoISO 8601 timestamp (default: current time)
valuesobject✅ YesKey-value pairs of measurements
metadataobject❌ NoAdditional context about the data point

Example Request

curl -X POST https://api.dakkio.io/api/data \
-H "X-API-Key: dakkio_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
-H "Content-Type: application/json" \
-d '{
"bucketId": "507f1f77bcf86cd799439011",
"dataSourceId": "507f1f77bcf86cd799439012",
"timestamp": "2024-01-15T10:30:00Z",
"values": {
"temperature": 22.5,
"humidity": 65,
"pressure": 1013.25
},
"metadata": {
"deviceId": "ESP32-001",
"location": "Living Room",
"batteryLevel": 85
}
}'

Response

Success Response

201 Created
{
"message": "Data point ingested successfully",
"dataPoint": {
"_id": "507f1f77bcf86cd799439016",
"bucketId": "507f1f77bcf86cd799439011",
"dataSourceId": "507f1f77bcf86cd799439012",
"timestamp": "2024-01-15T10:30:00Z",
"values": {
"temperature": 22.5,
"humidity": 65,
"pressure": 1013.25
},
"metadata": {
"deviceId": "ESP32-001",
"location": "Living Room",
"batteryLevel": 85
},
"createdAt": "2024-01-15T10:30:05Z"
}
}

Error Responses

400 Bad RequestValidation Error
{
"error": "Validation Error",
"message": "Invalid request parameters",
"details": [
{
"path": ["body", "bucketId"],
"message": "Expected string, received undefined"
}
]
}
401 UnauthorizedInvalid API Key
{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}
404 Not FoundBucket Not Found
{
"error": "Not Found",
"message": "Bucket not found"
}

Code Examples

JavaScript/Node.js

const axios = require('axios');

async function ingestData() {
try {
const response = await axios.post(
'https://api.dakkio.io/api/data',
{
bucketId: '507f1f77bcf86cd799439011',
dataSourceId: '507f1f77bcf86cd799439012',
timestamp: new Date().toISOString(),
values: {
temperature: 22.5,
humidity: 65,
pressure: 1013.25
},
metadata: {
deviceId: 'ESP32-001',
location: 'Living Room',
batteryLevel: 85
}
},
{
headers: {
'X-API-Key': process.env.DAKKIO_API_KEY,
'Content-Type': 'application/json'
}
}
);

console.log('Success:', response.data);
} catch (error) {
console.error('Error:', error.response.data);
}
}

ingestData();

Python

import requests
import os
from datetime import datetime

def ingest_data():
response = requests.post(
'https://api.dakkio.io/api/data',
headers={
'X-API-Key': os.environ['DAKKIO_API_KEY'],
'Content-Type': 'application/json'
},
json={
'bucketId': '507f1f77bcf86cd799439011',
'dataSourceId': '507f1f77bcf86cd799439012',
'timestamp': datetime.utcnow().isoformat() + 'Z',
'values': {
'temperature': 22.5,
'humidity': 65,
'pressure': 1013.25
},
'metadata': {
'deviceId': 'ESP32-001',
'location': 'Living Room',
'batteryLevel': 85
}
}
)

if response.status_code == 201:
print('Success:', response.json())
else:
print('Error:', response.json())

ingest_data()

Go

package main

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)

type DataPoint struct {
BucketId string `json:"bucketId"`
DataSourceId string `json:"dataSourceId"`
Timestamp string `json:"timestamp"`
Values map[string]interface{} `json:"values"`
Metadata map[string]interface{} `json:"metadata"`
}

func ingestData() error {
data := DataPoint{
BucketId: "507f1f77bcf86cd799439011",
DataSourceId: "507f1f77bcf86cd799439012",
Timestamp: time.Now().UTC().Format(time.RFC3339),
Values: map[string]interface{}{
"temperature": 22.5,
"humidity": 65,
"pressure": 1013.25,
},
Metadata: map[string]interface{}{
"deviceId": "ESP32-001",
"location": "Living Room",
"batteryLevel": 85,
},
}

jsonData, err := json.Marshal(data)
if err != nil {
return err
}

req, err := http.NewRequest("POST", "https://api.dakkio.io/api/data", bytes.NewBuffer(jsonData))
if err != nil {
return err
}

req.Header.Set("X-API-Key", os.Getenv("DAKKIO_API_KEY"))
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusCreated {
fmt.Println("Success!")
} else {
fmt.Printf("Error: %d\n", resp.StatusCode)
}

return nil
}

func main() {
if err := ingestData(); err != nil {
fmt.Println("Error:", err)
}
}

Arduino/ESP32

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* apiKey = "dakkio_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6";
const char* bucketId = "507f1f77bcf86cd799439011";
const char* dataSourceId = "507f1f77bcf86cd799439012";

void ingestData(float temperature, float humidity, float pressure) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;

http.begin("https://api.dakkio.io/api/data");
http.addHeader("Content-Type", "application/json");
http.addHeader("X-API-Key", apiKey);

StaticJsonDocument<512> doc;
doc["bucketId"] = bucketId;
doc["dataSourceId"] = dataSourceId;
doc["timestamp"] = "2024-01-15T10:30:00Z"; // Use NTP

JsonObject values = doc.createNestedObject("values");
values["temperature"] = temperature;
values["humidity"] = humidity;
values["pressure"] = pressure;

JsonObject metadata = doc.createNestedObject("metadata");
metadata["deviceId"] = "ESP32-001";
metadata["location"] = "Living Room";

String payload;
serializeJson(doc, payload);

int httpCode = http.POST(payload);

if (httpCode == 201) {
Serial.println("Data sent successfully!");
} else {
Serial.printf("Error: %d\n", httpCode);
}

http.end();
}
}

Best Practices

1. Use Batch Ingestion for Multiple Points

If you have multiple data points, use the batch endpoint instead:

// ❌ BAD: 100 individual requests
for (let i = 0; i < 100; i++) {
await axios.post('/api/data', dataPoint);
}

// ✅ GOOD: 1 batch request
await axios.post('/api/data/batch', {
bucketId: '...',
dataPoints: [...100 data points...]
});

2. Always Use UTC Timestamps

// ✅ GOOD
timestamp: new Date().toISOString() // "2024-01-15T10:30:00.123Z"

// ❌ BAD
timestamp: Date.now() // Unix milliseconds
timestamp: "15/01/2024" // Wrong format

3. Include Device Metadata

Help with debugging and monitoring:

{
"values": { "temperature": 22.5 },
"metadata": {
"deviceId": "ESP32-001",
"firmwareVersion": "1.2.3",
"batteryLevel": 85,
"signalStrength": -65
}
}

4. Implement Retry Logic

async function ingestWithRetry(data, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await axios.post(url, data, config);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
}
}
}

5. Handle Errors Gracefully

try {
await ingestData();
} catch (error) {
if (error.response?.status === 401) {
// Invalid API key - check configuration
} else if (error.response?.status === 404) {
// Bucket not found - verify bucketId
} else if (error.response?.status === 429) {
// Rate limit - implement backoff
} else {
// Log and retry later
}
}

Try It Now

Test this endpoint in the API Playground.