AsyncAPI event docs¶
The VeriOps event system provides asynchronous, event-driven communication for project lifecycle changes. AsyncAPI 2.6.0 contracts define channel schemas, delivery guarantees, and payload formats for three event channels.
Broker and transport¶
| Setting | Value |
|---|---|
| AsyncAPI version | 2.6.0 |
| Protocol | AMQP 0.9.1 (RabbitMQ) |
| Broker | amqp://events.veriops.example:5672 |
| WebSocket bridge | wss://events.veriops.example/ws |
| Authentication | Bearer token in connection header or SASL PLAIN |
| Delivery guarantee | At-least-once |
| Message retention | 7 days |
| Max payload size | 256 KB |
| Default consumer group | veriops-consumers |
| Heartbeat interval | 60 seconds |
Channel catalog¶
The VeriOps event system publishes events on three channels. All channels use JSON-encoded payloads with a standard envelope format.
| Channel | Direction | Payload type | Trigger | Description |
|---|---|---|---|---|
project.updated |
Publish (server to client) | ProjectUpdatedEvent |
Project status or name changes | Fires on every PUT /v1/projects/{id} that modifies the resource |
project.created |
Publish (server to client) | ProjectCreatedEvent |
New project created | Fires on every POST /v1/projects |
task.completed |
Publish (server to client) | TaskCompletedEvent |
Task status changes to done |
Fires when a task reaches terminal status |
Event envelope format¶
Every event uses a standard envelope that wraps the domain-specific payload:
{
"event_id": "evt_01abc789",
"event_type": "project.updated",
"occurred_at": "2026-03-19T14:30:00Z",
"producer": "veriops-core-service",
"trace_id": "tr_abc123def456",
"schema_version": "1.0.0",
"data": {}
}
Envelope fields¶
| Field | Type | Description |
|---|---|---|
event_id |
string | Unique event identifier for idempotency (format: evt_*) |
event_type |
string | Channel name matching the AsyncAPI contract |
occurred_at |
string (ISO 8601) | Timestamp when the event occurred |
producer |
string | Service that emitted the event |
trace_id |
string | Distributed tracing ID for correlation |
schema_version |
string | Payload schema version (semver) |
data |
object | Domain-specific payload (see below) |
Channel: project.updated¶
Fires when a project status or name changes.
Payload schema:
{
"event_id": "evt_01abc789",
"event_type": "project.updated",
"occurred_at": "2026-03-19T14:30:00Z",
"producer": "veriops-core-service",
"trace_id": "tr_abc123def456",
"schema_version": "1.0.0",
"data": {
"project_id": "prj_abc123",
"status": "active",
"previous_status": "draft",
"updated_by": "usr_456",
"updated_fields": ["status"]
}
}
Payload fields (data):
| Field | Type | Description |
|---|---|---|
project_id |
string | Project ID (format: prj_*) |
status |
string | New status: draft, active, archived |
previous_status |
string | Status before the change |
updated_by |
string | User ID who made the change |
updated_fields |
array of strings | List of fields that changed |
Channel: project.created¶
Fires when a new project is created.
Payload schema:
{
"event_id": "evt_02ABCD456",
"event_type": "project.created",
"occurred_at": "2026-03-19T15:00:00Z",
"producer": "veriops-core-service",
"trace_id": "tr_def456ghi789",
"schema_version": "1.0.0",
"data": {
"project_id": "prj_def456",
"name": "Mobile App Launch",
"status": "active",
"created_by": "usr_789"
}
}
Channel: task.completed¶
Fires when a task status changes to done.
Payload schema:
{
"event_id": "evt_03cde789",
"event_type": "task.completed",
"occurred_at": "2026-03-19T16:00:00Z",
"producer": "veriops-task-service",
"trace_id": "tr_ghi789jkl012",
"schema_version": "1.0.0",
"data": {
"task_id": "tsk_abc123",
"project_id": "prj_abc123",
"title": "Design homepage mockup",
"completed_by": "usr_456",
"duration_seconds": 7200
}
}
Delivery semantics¶
| Property | Value | Notes |
|---|---|---|
| Guarantee | At-least-once | Events may be delivered more than once |
| Ordering key | data.project_id |
Events for the same project arrive in order |
| Deduplication | Use event_id |
Store processed event IDs for idempotency checks |
| Retry policy | 3 retries with exponential backoff | Initial delay 5 seconds, max delay 60 seconds |
| Dead-letter queue | {channel}.dlq |
Failed events route here after 3 retries |
| Consumer acknowledgment | Manual ACK required | Unacknowledged messages redeliver after 300 seconds |
| Message TTL | 7 days | Messages expire from the queue after 7 days |
Consumer code examples¶
JavaScript (WebSocket bridge)¶
// Subscribe to project update events via WebSocket bridge
// Requires: valid bearer token and active WebSocket connection
const ws = new WebSocket('wss://events.veriops.example/ws', [], {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const processedEvents = new Set();
ws.addEventListener('open', () => {
ws.send(JSON.stringify({
action: 'subscribe',
channels: ['project.updated', 'project.created']
}));
console.log('Subscribed to project event channels');
});
ws.addEventListener('message', (event) => {
const payload = JSON.parse(event.data);
// Idempotency check: skip duplicate events
if (processedEvents.has(payload.event_id)) {
console.log('Skipping duplicate event:', payload.event_id);
return;
}
processedEvents.add(payload.event_id);
console.log('Event received:', payload.event_type, payload.data.project_id);
// Process the event here
});
Python (AMQP direct)¶
import json
import pika
# Connect to the AMQP broker
# Requires: pika library (pip install pika) and valid credentials
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host='events.veriops.example',
port=5672,
credentials=pika.PlainCredentials('YOUR_USERNAME', 'YOUR_PASSWORD')
)
)
channel = connection.channel()
channel.queue_declare(queue='my-consumer', durable=True)
channel.queue_bind(queue='my-consumer', exchange='veriops.events', routing_key='project.updated')
processed_ids = set()
def on_message(ch, method, properties, body):
event = json.loads(body)
if event['event_id'] in processed_ids:
ch.basic_ack(delivery_tag=method.delivery_tag)
return
processed_ids.add(event['event_id'])
print(f"Project {event['data']['project_id']} status: {event['data']['status']}")
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue='my-consumer', on_message_callback=on_message)
channel.start_consuming()
Interactive event tester¶
Enter a test event payload and send it to the sandbox WebSocket bridge.
Sandbox mode
Events route to a public WebSocket echo sandbox. The endpoint field below auto-fills with the sandbox URL. No API key is required for sandbox requests.
Error handling¶
| Error | Cause | Resolution |
|---|---|---|
CONNECTION_REFUSED |
Broker unreachable | Verify events.veriops.example:5672 is accessible from your network |
AUTH_FAILED |
Invalid credentials | Check bearer token or SASL credentials |
CHANNEL_NOT_FOUND |
Invalid channel name | Use exact channel names from the catalog above |
PAYLOAD_TOO_LARGE |
Message exceeds 256 KB | Reduce payload size or split into multiple events |
CONSUMER_TIMEOUT |
No ACK within 300 seconds | Acknowledge messages faster or increase prefetch count |
Next steps¶
- WebSocket event playground for bidirectional real-time messaging
- REST API reference for synchronous CRUD operations
- Tutorial: launch your first integration to subscribe to events end-to-end