API reference · Hubtask API 0.1.0
jumble
GET /jumble/entries
The jumble, newest first
Everything that arrived and what became of it. The raw content is answered here - to a credential that may read the workspace's entries - and nowhere that travels: it appears in no event payload, no log and no audit entry.
Query parameters
Responses
200One page of the jumble JumbleEntryPage4XXAn error per RFC 9457 Problem
curl -X GET "$HUBTASK_URL/jumble/entries" \ -H "Authorization: Bearer $HUBTASK_TOKEN" POST /jumble/entries
Put something in the jumble
The near channels: a quick capture or a plain API call, stored as an entry and announced as jumble.entry_received - which is what fires a JUMBLE_ENTRY automation rule. The two far channels are not a caller's to claim: EMAIL and WEBHOOK name the intakes that authenticate their own way, and an entry claiming one through this route would be forging its provenance. Attachments name media objects already uploaded through the media pipeline - never a second storage path - and each has to be sealed before it can be referenced here.
Headers
Request body application/json — JumbleEntrySubmit
Responses
201Caught JumbleEntry4XXAn error per RFC 9457 Problem
Codes this operation names
curl -X POST "$HUBTASK_URL/jumble/entries" \ -H "Authorization: Bearer $HUBTASK_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "channel": "API", "sender": "string", "raw_subject": "string", "raw_body": "string", "attachments": [ "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c" ]}' POST /jumble/entries/{entryId}:convert
Turn an entry into work
Creates a work item at the named destination - through the same use case a plain create goes through, with the same rights checked there - records the provenance on both sides (origin_jumble_id on the item, target_item_id on the entry), settles the entry as PROCESSED and announces jumble.entry_converted. Exactly once: a second conversion of the same entry is refused, and two racing produce one item and one refusal. The title defaults to the entry's subject, then to the first line of its body. An entry with no text - an attachment alone - needs a title in the request.
Path parameters
Headers
Request body application/json — JumbleEntryConvert
Responses
200Converted, with the target item on the entry JumbleEntry4XXAn error per RFC 9457 Problem
Codes this operation names
curl -X POST "$HUBTASK_URL/jumble/entries/{entryId}:convert" \ -H "Authorization: Bearer $HUBTASK_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "collection_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c", "bucket_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c", "title": "string", "type": "TASK"}' POST /jumble/entries/{entryId}:suggest
Ask AI what this entry should become
Asks the workspace's AI provider to propose a title, notes, a due date and labels for one entry. It proposes and changes nothing: what comes back is a suggestion, read through GET /suggestions, and it becomes a work item only when somebody converts the entry. Asynchronous, and answered 202. An AI call reaches somebody else's machine, so it never sits in a request — the suggestion appears when the provider has answered. Asking twice produces two proposals rather than one refusal: a duplicate suggestion is something somebody dismisses, which is the whole safety of a suggestion being a record. A workspace with no provider, or one that has not consented to AI processing, is answered 503 with the detail code ai.unavailable: nothing is queued and nothing is sent.
Path parameters
Headers
Responses
Codes this operation names
curl -X POST "$HUBTASK_URL/jumble/entries/{entryId}:suggest" \ -H "Authorization: Bearer $HUBTASK_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" POST /jumble/entries/{entryId}:dismiss
Decide against an entry
A state, not a deletion: the entry stays readable, and the retention engine ages it out by rule rather than by hand. Only a NEW entry can be dismissed - an entry is decided about exactly once.
Path parameters
Headers
Responses
200Dismissed JumbleEntry4XXAn error per RFC 9457 Problem
curl -X POST "$HUBTASK_URL/jumble/entries/{entryId}:dismiss" \ -H "Authorization: Bearer $HUBTASK_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" POST /jumble/intake:rotate-token
Mint the address the jumble accepts webhooks on
The tenant's one intake credential, the inbound trigger's discipline applied to the inbox: 32 bytes of entropy, the tenant named in clear inside the token, hashed over the whole presented string under the intake's own purpose label, and answered once - no later read can produce it. Rotating is how one is revoked: there is exactly one address per tenant and the replacement happens in a single statement, so the old token and the new one never both open the intake.
Headers
Responses
200Minted, with the token shown for the only time JumbleIntakeToken4XXAn error per RFC 9457 Problem
curl -X POST "$HUBTASK_URL/jumble/intake:rotate-token" \ -H "Authorization: Bearer $HUBTASK_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" POST /jumble/inbound/{token}
Deliver something into the jumble from outside
The WEBHOOK channel: an external system posts a small JSON shape - sender, subject, body, all optional but not all empty - and it lands as an entry, fires jumble.entry_received, and waits for a person or a rule to decide about it. The token authenticates the tenant, never a person: the entry records no actor, and the body is data end to end - bounded twice (the transfer by the request middleware, the entry by its own field bounds), matched by rules as data, and rendered as instructions to nothing. Every reason not to serve answers the same 404 with the same body - an unknown token, a rotated one, a tenant that never minted one. Distinguishing them would answer questions for whoever is trying tokens.
Path parameters
Request body application/json — JumbleIntakeDelivery
Responses
201Caught, with the entry it became JumbleIntakeAccepted4XXAn error per RFC 9457 Problem
Codes this operation names
curl -X POST "$HUBTASK_URL/jumble/inbound/{token}" \ -H "Content-Type: application/json" \ -d '{ "sender": "string", "subject": "string", "body": "string"}' POST /jumble/mail/{token}
Deliver a mail into the jumble
The EMAIL channel. The body is the message as it arrived - RFC 5322 bytes, headers included - and the transport is webhook-first: an operator points a mail-to-webhook bridge, their MTA or their provider's push at this address, and the bytes are what any of them can forward without agreeing on a shape. The parser is transport-independent and defensive. MIME is walked with bounds on parts, depth, attachment count and attachment size, checked before anything is allocated; attachments go through the media pipeline with its size and type discipline, never a second storage path; and the HTML alternative of a message that also had a plain part is kept as text beside it. No HTML is ever rendered server-side. The sender is data, never an identity: a From header authenticates nothing, and what authenticates is the token. A message the parser cannot read still lands, as an entry carrying the raw payload - a jumble exists to catch, and "unparseable" is a thing to catch. A message that breaks one of the bounds is refused with the code that says which, because "raise the bound" and "look at the entry" are different answers. Every reason not to serve answers the same 404, as the webhook intake's does.
Path parameters
Request body message/rfc822
Responses
201Caught, with the entry it became JumbleIntakeAccepted4XXAn error per RFC 9457 Problem
curl -X POST "$HUBTASK_URL/jumble/mail/{token}"