POST /api/ingest
curl --request POST \
--url https://sluice.sh/api/api/ingestimport requests
url = "https://sluice.sh/api/api/ingest"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://sluice.sh/api/api/ingest', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sluice.sh/api/api/ingest",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sluice.sh/api/api/ingest"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sluice.sh/api/api/ingest")
.asString();require 'uri'
require 'net/http'
url = URI("https://sluice.sh/api/api/ingest")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyIngestion
POST /api/ingest
Ingest events from the Sluice SDK or Go agent.
POST
/
api
/
ingest
POST /api/ingest
curl --request POST \
--url https://sluice.sh/api/api/ingestimport requests
url = "https://sluice.sh/api/api/ingest"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://sluice.sh/api/api/ingest', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sluice.sh/api/api/ingest",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sluice.sh/api/api/ingest"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sluice.sh/api/api/ingest")
.asString();require 'uri'
require 'net/http'
url = URI("https://sluice.sh/api/api/ingest")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyAccepts a batch of normalized events from the SDK or agent. This is the primary data ingestion endpoint — all job, worker, and queue data enters Sluice through this endpoint.
Exactly one of
Authentication
API key viaAuthorization: Bearer sk_... header.
Request body
{
"events": [
{
"type": "job_state_change",
"timestamp": "2026-02-27T10:30:00.000Z",
"framework": "celery",
"connectionId": "550e8400-e29b-41d4-a716-446655440000",
"job": {
"externalId": "abc123-def456",
"name": "app.tasks.send_email",
"queue": "default",
"state": "completed",
"previousState": "active",
"workerId": "celery@worker-1",
"attempt": 1,
"createdAt": "2026-02-27T10:29:55.000Z",
"startedAt": "2026-02-27T10:29:56.000Z",
"completedAt": "2026-02-27T10:30:00.000Z"
}
}
]
}
Event fields
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Event type identifier (e.g., job_state_change, worker_state_change, queue_snapshot). |
timestamp | string | Yes | ISO 8601 datetime. |
framework | string | Yes | One of celery, bullmq, sidekiq. |
connectionId | string | Yes | UUID of the connection. Must match the authenticated API key’s connection. |
job | object | No | Job event payload. Present for job-related events. |
worker | object | No | Worker event payload. Present for worker-related events. |
queue | object | No | Queue snapshot payload. Present for queue metrics. |
job, worker, or queue should be present per event.
Job payload
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | Yes | Framework-native job ID (Celery task UUID). Max 512 chars. |
name | string | Yes | Task/job type name (e.g., app.tasks.send_email). Max 1024 chars. |
queue | string | No | Queue name. Max 255 chars. |
state | string | Yes | Unified state: unknown, queued, scheduled, active, completed, failed, retrying, cancelled. |
previousState | string | No | Previous unified state. |
workerId | string | No | Worker identifier. Max 512 chars. |
attempt | integer | No | Current attempt number (1-indexed). |
maxRetries | integer | No | Configured retry limit. |
progress | number | No | Progress value between 0.0 and 1.0. |
error | string | No | Error message on failure. Max 10,000 chars. |
stacktrace | string | No | Full traceback on failure. Max 50,000 chars. |
createdAt | string | No | ISO 8601 — when the job was dispatched. |
startedAt | string | No | ISO 8601 — when execution began. |
completedAt | string | No | ISO 8601 — when execution finished. |
extensions | object | No | Framework-specific fields that don’t map to the common model. |
Worker payload
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | Yes | Framework-native worker ID (e.g., celery@worker-1). |
hostname | string | Yes | Worker hostname. |
pid | integer | No | Worker process ID. |
state | string | Yes | One of online, busy, idle, offline, heartbeat. |
concurrency | integer | No | Max concurrent jobs. |
activeJobs | integer | No | Currently processing count. |
queues | string[] | No | Queues this worker consumes. |
metadata | object | No | Framework-specific metadata (software versions, pool type, etc.). |
Queue payload
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Queue name. Max 255 chars. |
depth | integer | Yes | Current number of pending jobs. |
consumers | integer | No | Number of active consumers. |
Limits
- Maximum 1,000 events per request.
- Maximum 5 MB request body.
- Free tier: 10,000 events per day. Resets at midnight UTC.
Response
{
"accepted": 42,
"rejected": 0,
"skipped": 3,
"truncated": 0,
"usage": {
"used": 8042,
"limit": 10000,
"remaining": 1958,
"resetAt": "2026-02-28T00:00:00.000Z"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request body failed schema validation.",
"docs_url": "https://docs.sluice.sh/troubleshooting/api-errors",
"details": {
"events": ["Array must contain at least 1 element(s)"]
}
}
}
{
"error": {
"code": "DAILY_LIMIT_EXCEEDED",
"message": "Daily limit reached (10,000 events). Previously ingested data is preserved. Upgrade for higher limits.",
"docs_url": "https://docs.sluice.sh/troubleshooting/usage-limits"
},
"usage": {
"used": 10000,
"limit": 10000,
"remaining": 0,
"resetAt": "2026-02-28T00:00:00.000Z"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
accepted | integer | Number of events successfully processed. |
rejected | integer | Number of events that failed validation or processing. |
skipped | integer | Number of duplicate events that were skipped. |
truncated | integer | Number of events dropped because the daily limit was reached mid-batch. |
usage | object | Current usage counters for the day. |
⌘I