Supported Formats
Every file type Madless accepts — and, more usefully, what happens to each one after it lands. Nothing here is stored as a blob and forgotten: every format on this page is understood on the way in, once, so that reading it back later is nearly free.
This table is not written down anywhere. It is rendered from the admission registry the keep door enforces, so a format listed here has a working reader behind it by construction. For your own space’s live answer — formats, ceilings, the artifacts each modality must produce, and every refusal code in its own wording — call GET /api/v1/keep/formats (concepts.read).
Words you type
The whole of what you wrote is parsed, versioned, searchable and citable.
kind: "text" · up to 40,000 of your characters — the text, not the HTML that stores it, so an & stored as & costs nothing; past that, or a note whose formatting takes it past 60,000 stored, a 422 too_long at the door · carries no file
A web page
The readable page and where it came from are both kept — and when the address is a document, the document itself is fetched, read and kept with it. A bare URL with nothing behind it is not.
kind: "link" · carries no file
Pictures
The original picture is kept, and what is in it is read into words you can search.
kind: "image" · up to 25 MB per file
Audio
The recording is kept and transcribed in full. Part of a transcript is not enough.
kind: "audio" · up to 500 MB per file · length capped by your plan (below)
Video
The recording is kept, what it shows is read, and anything said in it is transcribed in full.
kind: "video" · up to 500 MB per file · length capped by your plan (below)
Documents
The original is kept and read end to end, with the place each passage came from.
kind: "document" · up to 25 MB per file
Several at once
Every block passes its own contract, or nothing is kept.
kind: "compose" · as many files as your space allows per concept — read it as max_files on GET /api/v1/keep/formats; one more is a 400 too_many_files
Limits
One ceiling per plan, whichever door a thing comes through: a clip recorded through POST /api/v1/keep and a file dragged into Drive are held to the same length — 5 minutes on Plus, 10 minutes on Pro. Starter uses its own shorter limit of 2 minutes. These are the plan catalogue’s own numbers, and a superadmin can lift them for a single space.
Over the cap, material is refused — never stored and left unreadable. An over-length keep is refused with code: "too_long" and a detail you can show verbatim — as a 422 when the length is known up front, otherwise on the intake receipt once it has been read. An over-length upload is probed once it lands, then purged whole — bytes and record together — and the owner is told why, with the ceiling named in minutes. Nothing is kept that cannot be read.
Every meter — AI credits, media minutes, images, storage, views with people — is readable at GET /api/v1/usage, which needs no scope and no entitlement, so check headroom there rather than discovering a cap through a refusal.
Storage is wider than reading
POST /api/v1/drive/uploads/sign holds a wider set of types than the list above, and the difference is deliberate: storage answers is this safe to hold, admission answers can this be read. A type outside the storage allowlist is a 400 at sign time, naming the type. A type storage accepts but no reader can read is a 422 at POST /api/v1/keep carrying code: "unsupported_format" — and no concept is created.
Send an accurate mime: nothing sniffs the extension, and it is what decides whether a file is transcribed, described or merely kept. The retired content_type spelling is a 400 too.
Getting things in
POST /api/v1/keep is the one door in. Its intent is a discriminated union on kind — text, link, image, audio, video, document or compose. There is no generic file kind: a format with no reader is not keepable. The door answers 202 with an intake receipt the moment the material is staged; poll GET /api/v1/keep/intake/{intake_id} until it reads admitted (with the concept_id) or refused (with the refusal’s code). An admitted concept lands in the Stack, or where you placed it while it was read, with PATCH /api/v1/keep/intake/{intake_id}.
Bytes never ride the keep body. Upload them first on the three-step drive path — sign, PUT to the signed URL, register — then hand the resulting fil_… to the media kind as file_id. Recipe 5 in the LLM Instructions walks the whole sequence.
One exception, and it needs no upload: a link whose address is a document — a PDF, a deck, a spreadsheet. Madless fetches it, reads it with the document reader, and keeps the file beside the URL, so the concept stays a link and the reading survives the page dying. The download is held to the same byte ceiling and the same storage quota an upload is.