Download OpenAPI specification:
Centralized event streaming API for the Grand Shooting ecosystem.
gs-stream-events collects events produced by company applications (Grand Shooting, Sourcing, Connect), stores them, and distributes them to authorized consumers through pull-based queues and a historical query API.
Every /v1/* route requires an API key passed in the Authorization
header:
Authorization: Bearer gs_live_xxxxxxxx...
gs_live_ (production) or gs_test_ (test).events:write, events:read, queues:read, queues:manage,
keys:manage, or * (full access).superadmin role (queue
management) or ownership of the resource (queue stats and alerts).OAuth 2.0 (JWT) authentication is also accepted on the same header for internal integrations.
Limits apply per account, per minute, depending on the route tier:
| Tier | Limit | Routes |
|---|---|---|
| STRICT | 10 req/min | Key management, queue creation/updates, alert configuration |
| STANDARD | 1,000 req/min | Event publishing |
| RELAXED | 5,000 req/min | Reads: queries, queue polling, stats, alerts |
Test keys (gs_test_) get one tenth of each limit. Every response includes
the X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset
headers; 429 responses also include Retry-After (seconds).
Webhooks have been replaced by consumer queues (managed SQS). Each consumer gets a dedicated queue, fed in real time according to its filters (event types, applications, accounts):
GET /v1/queues/{name}/messages with long-polling
(up to 20 s wait, 10 messages max). Received messages become invisible
for the duration of the visibilityTimeout (30 s by default).DELETE /v1/queues/{name}/messages with the
receiptHandles. An unacknowledged message becomes visible again after
the visibilityTimeout and will be redelivered.Unconsumed messages are deleted after the queue's retention period (7 days by default, 14 days max). Built-in monitoring automatically alerts on backlog, idle consumers, or retention-loss risk (see the Alerts section).
POST /v1/events/query uses cursor pagination: the response contains
cursor (an opaque internal identifier) and hasMore. Pass the received
cursor back in the next request to get the following page.
eventType has 2 or 3 dot-separated segments, each starting with a
lowercase letter (letters, _, -): photo.uploaded,
user.account.updated.
Event publishing (single or batch) and querying of stored history (18-month hot storage retention).
Publishes a single event. Required scope: events:write.
The caller must have access to the scope.accountId account.
eventId and timestamp are generated automatically when omitted.
| eventId | string <uuid> Generated automatically when omitted | ||||||||||
| eventType required | string^[a-z][a-z_-]*(\.[a-z][a-z_-]*){1,2}$ 2 or 3 dot-separated lowercase segments | ||||||||||
| timestamp | string <date-time> Event date (default = now) | ||||||||||
required | object | ||||||||||
| |||||||||||
required | object Who triggered the event | ||||||||||
| |||||||||||
required | object What the event is about (determines access rights) | ||||||||||
| |||||||||||
required | object Business content of the event | ||||||||||
| |||||||||||
object | |||||||||||
| |||||||||||
{- "eventId": "d6703cc8-9e79-415d-ac03-a4dc7f6ab43c",
- "eventType": "photo.uploaded",
- "timestamp": "2019-08-24T14:15:22Z",
- "source": {
- "application": "grand-shooting",
- "version": "2.31.0",
- "environment": "development"
}, - "actor": {
- "userId": "string",
- "accountId": "string",
- "role": "string"
}, - "scope": {
- "accountId": "string",
- "resourceType": "photo",
- "resourceId": "string"
}, - "payload": { },
- "metadata": { }
}{- "eventId": "string"
}Publishes up to 100 events in a single request. Required scope:
events:write. Invalid events are rejected individually (errors
field) without blocking the others; duplicate eventIds are silently
ignored.
required | Array of objects (EventInput) <= 100 items | ||||||||||||||||
Array (<= 100 items)
| |||||||||||||||||
{- "events": [
- {
- "eventId": "d6703cc8-9e79-415d-ac03-a4dc7f6ab43c",
- "eventType": "photo.uploaded",
- "timestamp": "2019-08-24T14:15:22Z",
- "source": {
- "application": "grand-shooting",
- "version": "2.31.0",
- "environment": "development"
}, - "actor": {
- "userId": "string",
- "accountId": "string",
- "role": "string"
}, - "scope": {
- "accountId": "string",
- "resourceType": "photo",
- "resourceId": "string"
}, - "payload": { },
- "metadata": { }
}
]
}{- "accepted": 0,
- "inserted": 0,
- "eventIds": [
- "string"
], - "errors": [
- {
- "index": 0,
- "error": "string"
}
]
}Searches stored events. Required scope: events:read.
Results are restricted to the accounts accessible by the caller and
sorted by descending date. The payloadFilter uses JSONB containment:
{"orderId": "123"} matches any payload containing this key/value pair.
object | |||||
| |||||
object | |||||
| |||||
object JSONB containment on the payload | |||||
| |||||
| limit | integer Default: 100 | ||||
| cursor | string Opaque cursor returned by the previous page | ||||
{- "filters": {
- "accountIds": [
- "string"
], - "eventTypes": [
- "string"
]
}, - "timeRange": {
- "from": "2019-08-24T14:15:22Z",
- "to": "2019-08-24T14:15:22Z"
}, - "payloadFilter": { },
- "limit": 100,
- "cursor": "string"
}{- "events": [
- {
- "eventId": "d6703cc8-9e79-415d-ac03-a4dc7f6ab43c",
- "eventType": "photo.uploaded",
- "timestamp": "2019-08-24T14:15:22Z",
- "source": {
- "application": "grand-shooting",
- "version": "2.31.0",
- "environment": "development"
}, - "actor": {
- "userId": "string",
- "accountId": "string",
- "role": "string"
}, - "scope": {
- "accountId": "string",
- "resourceType": "photo",
- "resourceId": "string"
}, - "payload": { },
- "metadata": { }
}
], - "cursor": "string",
- "hasMore": true
}Management of distribution queues (creation, filters, configuration).
Creating, updating, listing all queues and deleting are restricted to
the superadmin role.
Superadmin only. Required scope: queues:manage.
Creates a distribution queue fed in real time according to its filters.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Lowercase letters, digits and hyphens; starts and ends with a letter or digit | ||||||||
object (QueueFilters) Event routing filters for the queue. An omitted array or | |||||||||
| |||||||||
object (QueueConfig) | |||||||||
| |||||||||
{- "name": "billing-events",
- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "billing-events",
- "status": "pending",
- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}, - "stats": {
- "approximateMessageCount": 0,
- "approximateMessagesDelayed": 0,
- "approximateMessagesNotVisible": 0,
- "lastPollAt": "2019-08-24T14:15:22Z"
}, - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "queues": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "billing-events",
- "status": "pending",
- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}, - "stats": {
- "approximateMessageCount": 0,
- "approximateMessagesDelayed": 0,
- "approximateMessagesNotVisible": 0,
- "lastPollAt": "2019-08-24T14:15:22Z"
}, - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
]
}Required scope: queues:read.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "billing-events",
- "status": "pending",
- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}, - "stats": {
- "approximateMessageCount": 0,
- "approximateMessagesDelayed": 0,
- "approximateMessagesNotVisible": 0,
- "lastPollAt": "2019-08-24T14:15:22Z"
}, - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}Superadmin only. Required scope: queues:manage.
Updates the filters, configuration or status (active/paused).
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
object (QueueFilters) Event routing filters for the queue. An omitted array or | |||||||||
| |||||||||
object (QueueConfig) | |||||||||
| |||||||||
| status | string Enum: "active" "paused" | ||||||||
{- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}, - "status": "active"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "billing-events",
- "status": "pending",
- "filters": {
- "eventTypes": [
- "photo.uploaded",
- "order.*"
], - "applications": [
- "grand-shooting"
], - "accountIds": [
- "string"
]
}, - "config": {
- "maxMessages": 10,
- "waitTimeSeconds": 20,
- "visibilityTimeout": 30,
- "retentionPeriod": 604800
}, - "stats": {
- "approximateMessageCount": 0,
- "approximateMessagesDelayed": 0,
- "approximateMessagesNotVisible": 0,
- "lastPollAt": "2019-08-24T14:15:22Z"
}, - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}Superadmin only. Required scope: queues:manage.
Deletes the queue and all the messages it contains — irreversible.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
{- "message": "string",
- "deletedAt": "2019-08-24T14:15:22Z"
}Receiving (long-polling) and acknowledging messages from a queue. See "Consuming events: the pull pattern" in the introduction.
Required scope: queues:read. Waits up to waitTimeSeconds for
messages to arrive. Received messages become invisible for
visibilityTimeout: acknowledge them before it expires, otherwise
they will be redelivered.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
| maxMessages | integer [ 1 .. 10 ] Default: 10 |
| waitTimeSeconds | integer [ 0 .. 20 ] Default: 20 |
| visibilityTimeout | integer [ 0 .. 43200 ] Default = queue configuration (30 s) |
{- "messages": [
- {
- "messageId": "string",
- "receiptHandle": "string",
- "body": null,
- "attributes": {
- "property1": "string",
- "property2": "string"
}
}
], - "meta": {
- "count": 0,
- "approximateNumberOfMessages": 0,
- "approximateNumberOfMessagesDelayed": 0,
- "approximateNumberOfMessagesNotVisible": 0
}
}Required scope: queues:read. Permanently deletes processed messages
(10 max per request). Partial failures are detailed in failed.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
| receiptHandles required | Array of strings <= 10 items |
{- "receiptHandles": [
- "string"
]
}{- "successful": [
- "string"
], - "failed": [
- {
- "receiptHandle": "string",
- "error": "string"
}
]
}Automatic queue monitoring (every 5 minutes): idle consumer
(idle_consumer), messages close to the retention limit
(retention_risk), abnormal backlog (backlog). Notifications go to
the operations team and, by email, to the recipients configured per
queue or per account (cascade: queue → account → system defaults).
Required scope: queues:read, restricted to the queue's owner account
(or superadmin). Instantaneous statistics + current alert state.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
{- "name": "string",
- "status": "pending",
- "stats": {
- "approximateMessageCount": 0,
- "approximateMessagesDelayed": 0,
- "approximateMessagesNotVisible": 0
}, - "retentionPeriod": 0,
- "alertState": {
- "state": "ok",
- "reasons": [
- {
- "code": "idle_consumer",
- "message": "string"
}
], - "firstTriggeredAt": "2019-08-24T14:15:22Z",
- "lastNotifiedAt": "2019-08-24T14:15:22Z",
- "evaluatedAt": "2019-08-24T14:15:22Z"
}
}Required scope: queues:read, restricted to the owner account (or
superadmin). Returns the queue's own configuration, the account
defaults, and the resulting effective configuration.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
{- "queueName": "string",
- "alertConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "accountDefaults": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "effectiveConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}
}Required scope: queues:manage, restricted to the owner account (or
superadmin). Partial configuration accepted — omitted fields inherit
from the account defaults, then the system defaults.
| name required | string [ 3 .. 80 ] characters ^[a-z0-9][a-z0-9-]*[a-z0-9]$ Example: billing-events Queue name |
| enabled | boolean Default: true | ||||||
object | |||||||
| |||||||
| recipients | Array of strings <email> <= 20 items [ items <email > ] Email recipients for notifications | ||||||
{- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}{- "queueName": "string",
- "alertConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "effectiveConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "updatedAt": "2019-08-24T14:15:22Z"
}Required scope: queues:read. Alert state of every queue of the
caller's account (all queues for a superadmin).
{- "queues": [
- {
- "name": "string",
- "accountId": "string",
- "status": "string",
- "alertState": "ok",
- "reasons": [
- {
- "code": "idle_consumer",
- "message": "string"
}
], - "firstTriggeredAt": "2019-08-24T14:15:22Z",
- "lastNotifiedAt": "2019-08-24T14:15:22Z",
- "evaluatedAt": "2019-08-24T14:15:22Z"
}
]
}{- "accountId": "string",
- "alertConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "systemDefaults": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "effectiveConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}
}Required scope: queues:manage. Applies to every queue of the account
that has no configuration of its own.
| enabled | boolean Default: true | ||||||
object | |||||||
| |||||||
| recipients | Array of strings <email> <= 20 items [ items <email > ] Email recipients for notifications | ||||||
{- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}{- "accountId": "string",
- "alertConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "effectiveConfig": {
- "enabled": true,
- "thresholds": {
- "maxOldestAgeRatio": 0.5,
- "maxIdleMinutes": 120,
- "maxDepth": 100000
}, - "recipients": [
- "user@example.com"
]
}, - "updatedAt": "2019-08-24T14:15:22Z"
}Required scope: keys:manage. The caller's role bounds what can be
created (an admin creates admin/user keys for their own account;
only a superadmin creates keys for other accounts). Outside
production, only test keys are created. The full key is returned
only at creation time.
| name required | string |
| role | string Enum: "superadmin" "admin" "user" |
| scopes | Array of strings |
| expiresAt | string <date-time> |
| isTest | boolean |
| accountId | string Superadmin only (key for another account) |
{- "name": "string",
- "role": "superadmin",
- "scopes": [
- "events:write",
- "events:read"
], - "expiresAt": "2019-08-24T14:15:22Z",
- "isTest": true,
- "accountId": "string"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "key": "gs_live_a1b2c3...",
- "name": "string",
- "scopes": [
- "string"
], - "expiresAt": "2019-08-24T14:15:22Z",
- "createdAt": "2019-08-24T14:15:22Z"
}Required scope: keys:manage. Visibility depends on the role: a user
sees their own keys, an admin those of their account, a superadmin
all of them.
{- "keys": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "keyPrefix": "gs_live_",
- "name": "string",
- "scopes": [
- "string"
], - "expiresAt": "2019-08-24T14:15:22Z",
- "lastUsedAt": "2019-08-24T14:15:22Z",
- "createdAt": "2019-08-24T14:15:22Z",
- "isActive": true
}
]
}