Ingestion API Reference

The Ingestion Service accepts logs and metrics from external systems and pipelines. All endpoints return 202 Accepted on success.

Base URL: http://localhost:3001 (local) or your deployed ingestion endpoint.

Authentication & Multi-tenancy

All endpoints require an API key when OPERYN_API_KEY is configured on the server. You can find or rotate your Organization's API Key in the Dashboard (Settings → Organization). In a multi-tenant environment, you must also provide your Organization ID to ensure data is routed to the correct account and service limits are enforced properly.

Pass the key in the x-api-key header, and your Organization ID in the x-organization-id header:

curl -X POST https://ingest.operyn.example.com/events/logs \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key-here" \
  -H "x-organization-id: org_123456789" \
  -d '{ ... }'

If x-organization-id is omitted, data is routed to the default organization, which is limited to 5 services. If OPERYN_API_KEY is not set on the server, endpoints are open (suitable for local development).


POST /events/logs

Ingest a single log event.

Request Body

FieldTypeRequiredDescription
servicestringYesName of the originating service (e.g. billing-service)
levelstringYesLog level: debug, info, warn, error, or fatal
messagestringYesThe log message content
timestampstringNoISO 8601 timestamp. Defaults to server time if omitted
traceIdstringNoDistributed trace ID for correlation
spanIdstringNoSpan ID within the trace
metadataobjectNoArbitrary key-value pairs (region, env, team, etc.)

Example

curl -X POST http://localhost:3001/events/logs \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -H "x-organization-id: org_123456789" \
  -d '{
    "service": "api-gateway",
    "level": "error",
    "message": "Upstream timeout connecting to auth-service",
    "traceId": "abc-123-def",
    "metadata": {
      "region": "us-east-1",
      "env": "prod",
      "team": "platform"
    }
  }'

Response — 202 Accepted

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "queued": true
}

POST /events/logs/batch

Ingest multiple log events in a single request.

Request Body

An array of log event objects (same schema as POST /events/logs).

Example

curl -X POST http://localhost:3001/events/logs/batch \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -H "x-organization-id: org_123456789" \
  -d '[
    {
      "service": "billing-service",
      "level": "error",
      "message": "Payment failed for customer 42"
    },
    {
      "service": "billing-service",
      "level": "warn",
      "message": "Retry attempt 3 for payment gateway"
    }
  ]'

Response — 202 Accepted

{
  "accepted": 2
}

POST /events/metrics

Ingest a single metric data point.

Request Body

FieldTypeRequiredDescription
servicestringYesName of the originating service
namestringYesMetric name (e.g. http_5xx_rate, cpu_utilization)
valuenumberYesNumeric value of the metric
unitstringYesUnit of measurement (e.g. percent, seconds, count)
timestampstringNoISO 8601 timestamp. Defaults to server time if omitted
labelsobjectNoString key-value pairs for dimensions (region, instance, etc.)

Example

curl -X POST http://localhost:3001/events/metrics \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -H "x-organization-id: org_123456789" \
  -d '{
    "service": "api-gateway",
    "name": "request_latency_p99",
    "value": 2.34,
    "unit": "seconds",
    "labels": {
      "region": "us-east-1",
      "env": "prod",
      "endpoint": "/api/v1/users"
    }
  }'

Response — 202 Accepted

{
  "id": "e23f8a1c-9b4d-4e7f-8a2b-1c3d4e5f6a7b",
  "queued": true
}

---

## POST /events/deployments

Record a deployment event to correlate with future incidents.

### Request Body

| Field | Type | Required | Description |
|---|---|---|---|
| `service` | `string` | Yes | Name of the service being deployed |
| `version` | `string` | Yes | Version or tag being deployed (e.g. `v1.2.3`) |
| `environment` | `string` | Yes | Environment (e.g. `production`, `staging`) |
| `gitHash` | `string` | No | Git commit hash |
| `timestamp` | `string` | No | ISO 8601 timestamp. Defaults to server time |
| `metadata` | `object` | No | Additional deployment context |

### Example

```bash
curl -X POST http://localhost:3001/events/deployments \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -H "x-organization-id: org_123456789" \
  -d '{
    "service": "payment-service",
    "version": "v2.0.1",
    "environment": "production",
    "gitHash": "a1b2c3d4",
    "metadata": {
      "deployedBy": "jenkins",
      "deployId": "job-123"
    }
  }'

Response — 202 Accepted

{
  "id": "c1a2b3c4-d5e6-4f7g-8h9i-j0k1l2m3n4o5",
  "queued": true
}

---

## Error Responses

### 401 Unauthorized

Returned when `x-api-key` is missing or invalid.

```json
{
  "statusCode": 401,
  "message": "Invalid or missing API key"
}

400 Bad Request

Returned when the request body fails Zod schema validation.

{
  "statusCode": 400,
  "message": "Invalid log event: ..."
}

Service Naming Conventions

Use consistent, lowercase, hyphenated names for the service field:

PatternExample
<service-name>billing-service
<team>-<service>payments-billing-service

Avoid spaces, underscores, or uppercase. The ingestion service trims whitespace but does not transform casing.

Include these fields in metadata (logs) or labels (metrics) for best results:

KeyDescriptionExample
envDeployment environmentprod, staging, dev
regionCloud region or data centreus-east-1, eu-west-1
clusterKubernetes cluster nameprod-eks-1
teamOwning teamplatform, payments
sourceOrigin of the datacloudwatch, gcp, fluent-bit, app

Rate Limits

No rate limits are enforced by default. For production deployments, consider placing a load balancer or API gateway in front of the ingestion service with appropriate rate limiting.

Interactive API Docs

When running locally, visit: