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
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | ✅ Yes | Your organization API key |
Content-Type | string | ✅ Yes | Must be application/json |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
bucketId | string | ✅ Yes | MongoDB ObjectId of the bucket |
dataSourceId | string | ✅ Yes | MongoDB ObjectId of the data source |
timestamp | string | ❌ No | ISO 8601 timestamp (default: current time) |
values | object | ✅ Yes | Key-value pairs of measurements |
metadata | object | ❌ No | Additional 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
}
}
Related Endpoints
- Batch Ingest Data - Send multiple data points at once
- Query Data - Retrieve time-series data
- Create Data Source - Define data source schema
Try It Now
Test this endpoint in the API Playground.