Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.velahq.xyz/docs/llms.txt

Use this file to discover all available pages before exploring further.

Data model

Account
  └── App (one account, many apps)
        ├── API Key          — ingest events into this app
        ├── Schema (many)    — defines the shape of each event type
        ├── Event (many)     — validated payloads stored by Vela
        ├── Notification Rule (many) — conditional alert triggers
        └── Destination (many)      — Slack / Discord / Email / Webhook
Everything in Vela is scoped to an App. An app is the boundary between your services — one app per microservice, per environment, or per product area. You decide.

Accounts

An account represents your organization. It can own multiple apps and has a plan (Free, Pro, Team) that controls event limits and app quotas. You authenticate with one or more client secrets for management operations.

Apps

An app is an isolated workspace. Everything — schemas, events, rules — belongs to an app.
PropertyDescription
nameHuman-readable label, e.g. Order Service
slugURL-safe unique ID, e.g. order-service
API keyvela_live_... — used only for event ingestion
Common patterns:
  • One app per microservice (payments, auth, fulfillment)
  • One app per environment (order-service-prod, order-service-staging)
  • One app per product (web-app, mobile-app)

Schemas

A schema defines the expected shape of an event payload. Every event sent to Vela is validated against the schema for its event name. Events without a matching schema are rejected with 400.

Why schemas matter

Without schemas, bad data silently enters your system. A schema enforces:
  • Required fields — the event is rejected if they are missing
  • Field typesstring, number, boolean, date, enum, object
  • Validation rules — min/max length, regex patterns, enum values
  • Metadata fields — optional contextual data like environment or trace ID

Example schema

{
  "eventName": "payment.failed",
  "description": "Fired when a payment attempt fails",
  "fields": [
    { "id": "f1", "name": "orderId",     "type": "string", "required": true  },
    { "id": "f2", "name": "amountCents", "type": "number", "required": true  },
    { "id": "f3", "name": "reason",      "type": "enum",   "required": true,
      "enumValues": ["card_declined", "insufficient_funds", "expired_card"] },
    { "id": "f4", "name": "attemptNum",  "type": "number", "required": false }
  ],
  "metadataFields": [
    { "id": "m1", "name": "environment", "type": "string" },
    { "id": "m2", "name": "traceId",     "type": "string" }
  ]
}

Field types

TypeDescriptionValidation
stringTextmin, max (length), pattern (regex)
numberInteger or floatmin, max
booleantrue or false
dateISO-8601 date string
enumOne of a fixed setenumValues array required
objectNested JSON
Use the CLI to manage schemas as JSON files in your repository. Schema changes become PR-reviewable, just like database migrations.

Events

Events are the core data unit. An event represents something that happened in your system.

Event fields

FieldRequiredDescription
eventyesMust match a registered schema’s eventName
datayesPayload validated against schema fields
levelyesinfo, warning, error, or success
customer_idnoOptional customer identifier for filtering
metadatanoOptional context validated against metadataFields
timestampnoISO-8601 — defaults to server ingest time

Event levels

LevelWhen to useExamples
infoNormal business eventsorder.placed, user.signed_up
successCompleted flowspayment.captured, email.delivered
warningDegraded, non-criticalretry.attempt, rate_limit_approaching
errorFailures needing attentionpayment.failed, webhook.error

Event lifecycle

POST /v1/ingest

Schema validation — reject 400 if invalid

Saved to PostgreSQL

Published to message bus (events.ingested)

┌─────────────────┬──────────────────────┐
▼                 ▼                      ▼
Rules engine   Realtime WebSocket    Future consumers
evaluates      pushes event to
conditions     connected dashboards

Matching rules publish notifications.deliver

Delivery sends to Slack / Discord / Email / Webhook

Attempt logged: status, response code, error

On failure: retry up to 3x (30s delay) → DLQ

Notification Rules

A rule watches for events of a specific type and fires when conditions match. Evaluation is real-time — rules trigger as soon as an event is ingested.

Rule fields

FieldDescription
nameHuman-readable label
eventNameWhich event type to watch
conditionsOptional payload filters — all must pass
actionsOne or more delivery targets
enabledToggle on/off without deleting

Conditions

A rule with no conditions fires for every matching event. Conditions filter by payload fields:
{
  "conditions": [
    { "field": "amountCents",    "operator": "gt",       "value": 10000 },
    { "field": "currency",       "operator": "eq",       "value": "USD" },
    { "field": "reason",         "operator": "in",       "value": ["card_declined", "fraud"] },
    { "field": "customerEmail",  "operator": "contains", "value": "@enterprise.com" }
  ]
}
OperatorDescription
eq / neqEquals / not equals
gt / gteGreater than / greater than or equal
lt / lteLess than / less than or equal
containsString contains substring
in / not_inValue is in / not in array

Actions

Each action points to a destination. A single rule can have multiple actions — alert Slack and email at the same time.
{
  "actions": [
    { "id": "a1", "destinationId": "dest-uuid", "channel": "slack",   "enabled": true  },
    { "id": "a2", "destinationId": "dest-uuid", "channel": "email",   "enabled": true  },
    { "id": "a3", "destinationId": "dest-uuid", "channel": "discord", "enabled": false }
  ]
}

Destinations

Destinations are delivery targets configured in the dashboard. Create them once, then reference by ID in rules.
TypeDescription
slackSlack incoming webhook — formatted block message
discordDiscord webhook — color-coded embed
emailEmail via Resend API
webhookCustom HTTP endpoint — POSTs full event payload as JSON
Destination credentials are encrypted at rest with AES-256-GCM.

Authentication

CredentialFormatPurposeHeader
Client secretvela_cs_...Management APIAuthorization: Bearer
API keyvela_live_...Event ingestion onlyx-api-key
The separation is intentional. Your API key travels with every ingest call — if it leaks, an attacker can only send events, not read or modify your data. See the credentials guide.