Skip to content

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

NameTypeRequiredDescription
cursorstring optional
sizeinteger
  • default: 50
  • minimum: 1
  • maximum: 200
optional
statusstring
  • NEW
  • PROCESSED
  • DISMISSED
optionalNarrow to one state.
channelstring
  • EMAIL
  • WEBHOOK
  • QUICK_CAPTURE
  • API
optionalNarrow to one way of arriving.

Responses

Example bash
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

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Request body application/json — JumbleEntrySubmit

NameTypeRequiredDescription
channelstring
  • QUICK_CAPTURE
  • API
  • default: "API"
optional
senderstring optionalOptional provenance text, e.g.
raw_subjectstring
  • maxLength: 500
optional
raw_bodystring optional
attachmentsarray of string (uuid) optionalSealed media objects to carry.

Responses

Codes this operation names

Example bash
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

NameTypeRequiredDescription
entryIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Request body application/json — JumbleEntryConvert

NameTypeRequiredDescription
collection_idstring (uuid) requiredThe destination.
bucket_idstring (uuid) optionalThe board column, when the destination has a board.
titlestring
  • maxLength: 500
optionalThe item's title.
typestring
  • TASK
  • WORK_PACKAGE
  • ACTIVITY
  • default: "TASK"
optional

Responses

  • 200 Converted, with the target item on the entry JumbleEntry
  • 4XX An error per RFC 9457 Problem

Codes this operation names

Example bash
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

NameTypeRequiredDescription
entryIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

  • 202 The provider will be asked by the job named here; the suggestion appears under /suggestions, and a refusal the job meets is its error_code JobRef
  • 503 An error per RFC 9457 Problem
  • 4XX An error per RFC 9457 Problem

Codes this operation names

Example bash
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

NameTypeRequiredDescription
entryIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

Example bash
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

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

Example bash
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

NameTypeRequiredDescription
tokenstring requiredThe tenant's intake token, which is the whole credential: this route carries no bearer authentication, and the URL is what the bridge stores.

Request body application/json — JumbleIntakeDelivery

NameTypeRequiredDescription
senderstring optionalWho the bridge says it came from.
subjectstring optional
bodystring optional

Responses

Codes this operation names

Example bash
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

NameTypeRequiredDescription
tokenstring requiredThe tenant's intake token, exactly as /jumble/inbound/{token} carries one: the URL is the whole credential, this route carries no bearer authentication, and the token names the tenant in clear inside itself because the lookup needs one before it can happen.

Request body message/rfc822

Responses

Example bash
curl -X POST "$HUBTASK_URL/jumble/mail/{token}"