BETA
Skip to content

Projects

Create and manage log projects. Each project has its own ingest token, retention settings, and streams.

Base URL: https://app.krafter.dev/api/v1

List Projects

Retrieve all log projects.

GET /logs/projects

Required scope: logs:read

Example Request

bash
curl https://app.krafter.dev/api/v1/logs/projects \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
{
  "data": [
    {
      "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
      "name": "My App",
      "description": "Production logs",
      "retention_days": 30,
      "daily_limit_mb": 500,
      "ingest_token_prefix": "krl_live_kp7",
      "created_at": "2025-01-15T10:00:00Z",
      "updated_at": "2025-01-15T10:00:00Z"
    },
    {
      "id": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
      "name": "Staging",
      "description": "Staging environment logs",
      "retention_days": 7,
      "daily_limit_mb": 100,
      "ingest_token_prefix": "krl_live_aab",
      "created_at": "2025-01-10T08:00:00Z",
      "updated_at": "2025-01-10T08:00:00Z"
    }
  ]
}

Create Project

Create a new log project. A unique ingest_token is generated automatically.

POST /logs/projects

Required scope: logs:write

Request Body

FieldTypeRequiredDescription
namestringYesDisplay name for the project. Must be unique within the team.
descriptionstringNoOptional description.
retention_daysintegerNoNumber of days to retain log entries. Range 1--90. Defaults to 7.
daily_limit_mbintegerNoDaily ingestion limit in megabytes. Must be greater than 0. Defaults to 500.

Example Request

bash
curl -X POST https://app.krafter.dev/api/v1/logs/projects \
  -H "Authorization: Bearer kr_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My App",
    "description": "Production logs",
    "retention_days": 30
  }'

Example Response

json
// 201 Created
{
  "data": {
    "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "name": "My App",
    "description": "Production logs",
    "retention_days": 30,
    "daily_limit_mb": 500,
    "ingest_token_prefix": "krl_live_kp7",
    "ingest_token": "krl_live_kp7tx2bm4qrs6vwy3jnh5zfd7acmeg2j",
    "created_at": "2025-01-15T10:00:00Z",
    "updated_at": "2025-01-15T10:00:00Z"
  }
}

TIP

Save the ingest_token from the response — it is returned only on creation and rotation. List, get, and update responses include ingest_token_prefix (the first 12 characters) for identification but never the full token. Your services will use the full token to send logs to the Ingest API.


Get Project

Retrieve details of a specific project.

GET /logs/projects/:id

Required scope: logs:read

Example Request

bash
curl https://app.krafter.dev/api/v1/logs/projects/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
{
  "data": {
    "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "name": "My App",
    "description": "Production logs",
    "retention_days": 30,
    "daily_limit_mb": 500,
    "ingest_token_prefix": "krl_live_kp7",
    "created_at": "2025-01-15T10:00:00Z",
    "updated_at": "2025-01-15T10:00:00Z"
  }
}

Update Project

Update an existing project. Only provided fields are changed.

PUT /logs/projects/:id

Required scope: logs:write

Request Body

FieldTypeRequiredDescription
namestringNoDisplay name for the project. Must remain unique within the team.
descriptionstringNoOptional description.
retention_daysintegerNoNumber of days to retain log entries. Range 1--90.
daily_limit_mbintegerNoDaily ingestion limit in megabytes. Must be greater than 0.

Example Request

bash
curl -X PUT https://app.krafter.dev/api/v1/logs/projects/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer kr_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "retention_days": 90,
    "daily_limit_mb": 500
  }'

Example Response

json
{
  "data": {
    "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "name": "My App",
    "description": "Production logs",
    "retention_days": 90,
    "daily_limit_mb": 500,
    "ingest_token_prefix": "krl_live_kp7",
    "created_at": "2025-01-15T10:00:00Z",
    "updated_at": "2025-01-16T09:30:00Z"
  }
}

Delete Project

Permanently delete a project and all its log data, streams, and alerts.

DELETE /logs/projects/:id

Required scope: logs:write

Example Request

bash
curl -X DELETE https://app.krafter.dev/api/v1/logs/projects/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

// 204 No Content

Rotate Ingest Token

Generate a new ingest token for a project. The old token is revoked immediately.

POST /logs/projects/:id/rotate_token

Required scope: logs:write

Example Request

bash
curl -X POST https://app.krafter.dev/api/v1/logs/projects/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/rotate_token \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
{
  "data": {
    "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "name": "My App",
    "description": "Production logs",
    "retention_days": 30,
    "daily_limit_mb": 500,
    "ingest_token_prefix": "krl_live_xn4",
    "ingest_token": "krl_live_xn4w7bm2tk6qrs3vwy5jnh7zfdcameg2p",
    "created_at": "2025-01-15T10:00:00Z",
    "updated_at": "2025-01-16T12:00:00Z"
  }
}

WARNING

After rotating, the old ingest token stops working immediately. Update all services that send logs to this project with the new token.


List Streams

List all streams that have been auto-discovered for a project. Streams are created automatically from the stream field in ingested log entries.

GET /logs/projects/:id/streams

Required scope: logs:read

Example Request

bash
curl https://app.krafter.dev/api/v1/logs/projects/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/streams \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
{
  "data": [
    {
      "id": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
      "name": "backend",
      "inserted_at": "2025-01-15T10:01:00Z"
    },
    {
      "id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
      "name": "worker",
      "inserted_at": "2025-01-15T10:02:00Z"
    },
    {
      "id": "e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
      "name": "auth",
      "inserted_at": "2025-01-15T10:03:00Z"
    }
  ]
}

Retention

Each project has a retention_days setting (range 1--90, default 7) that controls how long log entries are kept. A nightly cleanup worker deletes entries older than the configured value on a per-project basis.

Retention safety net

In addition to your project's retention_days (enforced nightly by the cleanup worker), the underlying ClickHouse log_entries table has a hard TTL of 90 days. Even if retention_days is misconfigured, the cleanup worker fails, or a project is left without a custom value, log entries older than 90 days are removed automatically by the storage engine. You cannot retain log entries beyond 90 days on the current Krafter platform — set retention_days to a value ≤ 90 and design downstream archival accordingly.

Daily Ingestion Limit

Each project carries a daily_limit_mb setting (default 500). When an ingest request is received, Krafter checks today's usage and rejects further entries with 429 Daily log ingestion limit exceeded once the threshold is reached.

What counts toward the limit

bytes_in for each accepted entry is computed from the payload string fields only — specifically message, stream, service, trace_id, span_id, and the JSON-encoded metadata object. HTTP framing, JSON encoding overhead (quotes, commas, brackets), the timestamp, and the level field are not counted. Treat daily_limit_mb as a soft cap on logical payload size, not as a wire-byte budget.

The counter resets at the start of each UTC day.

Limit is per-team in practice, not per-project

The daily_limit_mb value lives on each project, but the enforcement counter (bytes_in) is aggregated per teamLogs.daily_limit_exceeded?/2 looks up today's total bytes for the project's team and compares it against that single project's daily_limit_mb.

In practice this means:

  • If a team has multiple projects, the lowest daily_limit_mb across those projects is what the team will hit first.
  • A second project on the same team with a higher limit will still see 429 once the team-wide aggregate crosses the first project's threshold.

This mismatch between field semantics ("per-project limit") and enforcement ("per-team aggregate") is tracked as a bug in the logs truth-up plan and will be reconciled in a follow-up PR. Until then, set daily_limit_mb consistently across projects on the same team to avoid surprises.

Built by Krafter Studio