Appearance
HTTPS pull API
Available now Get your consumer connection's client id and secret in theportal, under Consumer connections. No request to RND and no deploy.
Your consumer app reads its own queue over HTTPS: receive a batch of messages, handle them, and acknowledge each one. No AWS account or AWS credentials are needed. The messages, their order and the delivery guarantees are the same as reading the queue directly (see Delivery).
In the URLs below, https://api.sombus.rnd-solutions.net/v1 is the Sandbox (use the Preview's base URL from Environments there), {t} is your workspace id and {c} is your client id.
Your credentials and token
Each consumer connection can have its own client id and secret, separate from any producer app's. In the portal, open Consumer connections and press Get client secret on the connection (developer role or above). The secret is shown once, with the URLs below filled in for that connection; only a hash is kept, so a lost secret can't be shown again, only rotated.
Swap them for an access token at the token service, exactly as a producer does (see Token service and workspace API):
bash
TOKEN=$(curl -s https://api.sombus.rnd-solutions.net/v1/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" -d grant_type=client_credentials | jq -r .access_token)Reuse the token for its whole hour. The client id is your consumer connection's id, so it is also the {c} in every pull URL. A consumer's token only reads its own queue: it can't publish, and a producer's token can't read a queue.
Rotate or revoke the secret
These work as for a producer's secret (see Credentials):
- Rotate secret gives a new secret. Choose how long the previous one keeps getting tokens: 24 hours (the default), 3 days, 1 hour, or none. Tokens issued before the rotation stop working within about 30 seconds, whichever secret they came from: get a new token and carry on. Stop old secret now ends the overlap early.
- Revoke secret stops the secret at once and its tokens within about 30 seconds. The connection and its queue stay. Press Get client secret for a new one when you need it; tokens of the old one never work again.
Tokens carry a credential_version claim that goes up with each rotation. Every change is recorded in your workspace's audit log. Only the organisation that owns the app manages its secret.
Receive messages
GET /v1/tenants/{t}/consumers/{c}/messages
bash
curl -s -H "Authorization: Bearer $TOKEN" \
"https://api.sombus.rnd-solutions.net/v1/tenants/$WORKSPACE/consumers/$CLIENT_ID/messages?max=10&wait=20"| Query parameter | Default | Range | Meaning |
|---|---|---|---|
max | 10 | 1 to 10 | At most this many messages |
wait | 20 | 0 to 20 | Long poll: seconds to wait for a message when none is ready. 0 answers at once |
visibility | 60 | 0 to 43200 | Seconds the received messages stay hidden from other receives while you handle them |
attempt | none | 1 to 128 printable ASCII characters, no spaces | A receive attempt id. If the answer is lost, retry with the same id within five minutes to get the same messages back instead of waiting for them to become visible again |
The answer is 200, with no messages when none arrived within wait:
json
{
"messages": [
{
"receipt_handle": "AQEB…",
"message_type": "story.context",
"correlation_id": "0192f5a0-…",
"topic": "som.story.context",
"producer_id": "c…",
"receive_count": 1,
"enqueued_at": "2026-09-25T10:15:02.114Z",
"envelope": { "som_version": "1.0.0", "message_id": "…", "payload": { … } }
}
]
}envelopeis the producer's message, as it was accepted. Only messages the bus accepted reach you.receipt_handleis what you acknowledge or release it with. It is only valid for this receive.receive_countcounts deliveries of this message, this one included. More than 1 means it was delivered before and not acknowledged in time.
Acknowledge
POST /v1/tenants/{t}/consumers/{c}/ack: you're done with these messages; they are removed.
bash
curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "receipt_handles": ["AQEB…", "AQEB…"] }' \
"https://api.sombus.rnd-solutions.net/v1/tenants/$WORKSPACE/consumers/$CLIENT_ID/ack"json
{ "acked": ["AQEB…"], "failed": [ { "receipt_handle": "AQEB…", "code": "ReceiptHandleIsInvalid", "message": "…" } ] }1 to 10 distinct receipt handles per request. Each handle succeeds or fails on its own, so the answer is 200 even when some fail. A handle fails when it is malformed or not from your queue. A message whose visibility ran out before you acknowledged it may already be delivered again: keep your processing idempotent (see Order and duplicates).
Release (nack)
POST /v1/tenants/{t}/consumers/{c}/nack: you can't handle these messages now; make them visible again, at once or after delay_seconds (0 to 43200, default 0).
json
{ "receipt_handles": ["AQEB…"], "delay_seconds": 30 }json
{ "nacked": ["AQEB…"], "failed": [] }A message delivered too many times without an acknowledgement moves to your dead-letter queue: after the connection's attempt limit, 5 unless you chose another when you created it. Once you've fixed the cause, redrive it back to your queue from the portal (see Dead-letter queues and replay).
A skill executor's registrations
GET /v1/tenants/{t}/consumers/{c}/skills: in a house, a skill executor reads the configured instances the house bound to its connection, with their values and authority scale. Same token, no parameters. See Registrations in the executor contract.
Order and duplicates
- Order per story. Messages of one
correlation_idarrive in the order the bus accepted them. While one of them is received and not yet acknowledged, released or timed out, the next ones of that story wait. Other stories are not held up. - At least once. A message can arrive more than once: after a lost answer, a visibility timeout or a release. Deduplicate on
message_id. - Snapshots. Keep the highest
sequence_numberperstory_id, as with any consumer.
A typical loop: receive with wait=20; handle each message; acknowledge the ones you handled; release the ones you want retried; repeat.
Limits
The pull routes are workspace routes, limited per connection like publishing: a consumer connection gets its own allowance when its client secret is issued: your organisation's quota tier (on standard, 20 requests a second, bursts of 40, and 100,000 requests a day). Receive, acknowledge and release all count, and a long poll that waits 20 seconds costs one request. The bus-wide limits apply as well (see Limits).
Errors
Refusals use the bus's usual body: { "accepted": false, "violations": [ { "rule": "…", "message": "…" } ] }.
| Status | Rule | Meaning | What to do |
|---|---|---|---|
| 400 | pull.bad_request | A query parameter or the body is malformed | Fix the request |
| 401 | producer.unauthenticated | Token missing, invalid, expired or for another environment | Get a new token |
| 403 | producer.not_registered | Valid token, but not an active consumer connection's (a producer's token, or a revoked or removed connection) | Use your consumer connection's credentials; restore the connection if it was revoked |
| 403 | tenant.mismatch | {t} is not your workspace | Use the tenant claim of your token |
| 403 | consumer.not_owner | {c} is not your connection | Use your client id |
| 429 | rate.limited, quota.exceeded | Over a limit | Back off and retry |
| 503 | consumer.queue_unavailable | Your queue is still being set up, or couldn't be reached | Retry after Retry-After |
| 503 | skills.unavailable | Your skill registrations couldn't be read | Keep what you read last; retry after Retry-After |
Revoking a consumer connection stops new tokens at once and the pull API within about 30 seconds; its queue is kept, and restoring it lets the same secret read again. Removing the connection deletes its queue and its credentials.
Next: Subscriptions and filters.