Skip to main content
The Ingestion API lets you push data into Causeloop from any source that doesn’t have a managed connector. A single HTTP call turns a raw signal into an Issue that participates in Causeloop’s pattern detection. All ingestion endpoints require a Bearer token with the ingest:write scope. See Authentication.

Endpoints at a glance

EndpointUse caseMax per call
POST /v1/ingest/eventsSingle raw signal1
POST /v1/ingest/batchPre-normalized issue records500
POST /v1/ingest/{source}/issuesSource-specific push with field validation1
GET /v1/ingest/status/{job_id}Poll async job status

Single event

Push one raw signal. Causeloop normalizes it and creates an Issue immediately. The response includes the new issue_id.
curl -X POST https://api.causeloop.ai/v1/ingest/events \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "custom_api",
    "external_id": "DEPLOY-2026-06-14-001",
    "title": "Deployment failed: payment-service v2.3.1",
    "body": "Health check timed out after 30s on 3/5 replicas.",
    "severity": "p1",
    "external_url": "https://ci.example.com/deploys/12345"
  }'
Response (202 Accepted)
{
  "accepted": 1,
  "rejected": [],
  "issue_id": "iss_01hx5f6g7h",
  "job_id": "ing_job_01hx5e5f6g"
}

Single event fields

source
string
default:"custom_api"
The source system identifier. Use a recognized value for richer pattern matching (see Source values). Unknown values are coerced to custom_api.
external_id
string
Your system’s unique identifier for this event. Used for deduplication — submitting the same external_id + source combination twice updates the existing issue rather than creating a duplicate.
title
string
Short description of the issue. Falls back to external_id if omitted.
body
string
Full description or error detail. Can be plain text or Markdown.
severity
string
default:"p3"
Priority level: p1 (critical), p2 (high), p3 (medium), p4 (low).
external_url
string
Link back to the issue in your source system.
metadata
object
Free-form key/value pairs. Stored as-is and available in the issue detail view.

Batch ingest

Push up to 500 pre-normalized issue records in a single call. Each record is processed independently — a failure on one record does not abort the rest.
curl -X POST https://api.causeloop.ai/v1/ingest/batch \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {
        "external_id": "JIRA-1234",
        "source": "jira",
        "title": "API gateway returning 503 on /checkout",
        "body": "Started after deploy at 14:32 UTC. Affects ~12% of requests.",
        "severity": "p1",
        "team": "platform",
        "source_created_at": "2026-06-14T14:35:00Z"
      },
      {
        "external_id": "JIRA-1235",
        "source": "jira",
        "title": "Cart service memory leak under sustained load",
        "severity": "p2",
        "team": "backend",
        "source_created_at": "2026-06-14T14:40:00Z"
      }
    ]
  }'
Response (202 Accepted)
{
  "accepted": 2,
  "rejected": [],
  "job_id": "ing_job_01hx5e5f7h",
  "issue_ids": ["iss_01hx5f6g7h", "iss_01hx5f6g8i"]
}
If any records fail validation, they appear in rejected with an index and reason:
{
  "accepted": 1,
  "rejected": [{ "index": 1, "code": "processing_error", "message": "title is required" }],
  "job_id": "ing_job_01hx5e5f7h",
  "issue_ids": ["iss_01hx5f6g7h"]
}

Batch record fields

records
IngestRecord[]
required
Array of records. Between 1 and 500 items.
Each IngestRecord:
external_id
string
required
Your system’s unique ID. Used for deduplication (with source).
source
string
required
Source system identifier. See Source values.
title
string
required
Issue title. 1–300 characters.
body
string
Full description.
severity
string
default:"p3"
p1 | p2 | p3 | p4
team
string
Team or squad responsible. Used for grouping in the dashboard.
external_url
string
URL back to the source record.
source_created_at
string
ISO 8601 timestamp when the issue was created in the source system.
source_updated_at
string
ISO 8601 timestamp of the last update in the source system.
connector_id
string
Associate this record with an existing connector. Optional.

Source-specific ingest

If you know the source system, use the source-specific endpoint for validated field requirements:
curl -X POST https://api.causeloop.ai/v1/ingest/jira/issues \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "JIRA-9999",
    "title": "Login failing for SSO users",
    "severity": "p1",
    "team": "auth"
  }'
Supported source paths: jira, servicenow, github, pagerduty, opsgenie, linear, zendesk, custom_api.

Checking job status

Batch and source-specific ingestion is asynchronous. Poll the job endpoint to track progress:
curl https://api.causeloop.ai/v1/ingest/status/ing_job_01hx5e5f6g \
  -H "Authorization: Bearer $TOKEN"
{
  "job_id": "ing_job_01hx5e5f6g",
  "status": "succeeded",
  "progress": 1.0,
  "result": {
    "accepted": 2,
    "rejected_count": 0,
    "total": 2
  },
  "created_at": "2026-06-14T15:00:00Z",
  "finished_at": "2026-06-14T15:00:03Z"
}
Job status values: pendingrunningsucceeded | partial | failed.

Source values

Use recognized source values for the best pattern detection. The following values are supported natively: jira · servicenow · github · pagerduty · opsgenie · linear · zendesk · slack · email · database · custom_api Any other value is accepted but coerced to custom_api.

How ingested records become issues

When Causeloop accepts a record:
  1. The external_id + source pair is checked for duplicates. If a matching issue exists, it is updated.
  2. The record is normalized: missing fields get defaults, severity is validated, and the source is resolved.
  3. A new Issue object is created and emitted to the pattern detection pipeline.
  4. Causeloop checks whether the issue matches an existing Pattern. If it does, the issue is linked and the pattern’s confidence score is updated.
Do not parse the JSON body before computing HMAC signatures for inbound webhooks — always sign the raw bytes. See Webhooks for details.

Limits

LimitValue
Records per batch500
title max length300 characters
Request body max size5 MB
Rate limit1,000 requests / minute per workspace