Docs · publish
How to publish an intent
Write a plain-text file: intent: 2, a type and a title header, a blank line, then the body. Put it at any HTTPS URL, ideally served as text/markdown; charset=utf-8. That is the whole standard. Optionally, post it to a directory like intentsmd.com so agents find it sooner.
1. Write the file
intent: 2 type: rfp title: Rust contractor wanted — 2 weeks, remote budget: 8000 EUR attr-remote: yes contact: https://acme.example/rfp/rust Need a Rust dev to harden a small HTTP service: SSRF review + fuzzing. Two weeks, remote, start ASAP. Reply with a rate and a link to prior work.
Headers are name: value lines, lowercase names, one space after the colon. The header block ends at the first blank line. Parsers ignore headers they don’t recognise (like budget above) and never reject a document for them.
2. Name it and host it
- Name:
<slug>.intents.mdis recommended. A bareintents.mdat your site root is the conventional index of your intents, linking to the rest. Any name is valid. - Host: any HTTPS URL: your site, a static host, a gist. No new ports, DNS records or registries.
- Serve it as
text/markdown; charset=utf-8. Keep documents under 1 MB and headers under 64 KB; link media by URL, never embed it.
Core headers
| Header | Status | Rule |
|---|---|---|
intent | Required | Format version integer. This spec: 2. |
type | Required | A content type (below) or any custom string. Unknown types render as post. |
title | Required | One line of plain text. |
published | Recommended | ISO 8601 date or datetime, UTC. |
updated | Recommended | ISO 8601, the last material change (status, price, terms). |
expires | Recommended | ISO 8601. After it, renderers show “expired” but never hide the content. |
status | Optional | active (default), sold or withdrawn. |
lang | Optional | ISO 639-1 code of the body’s language. |
issuer | Optional | Display name of the publisher. |
issuer-url | Optional | HTTPS URL of the publisher’s site, used for L2 key binding. |
id | Optional | Stable identifier. Self-declared: offers anchor to URL + hash, never to id. |
prev | Optional | sha256 fingerprint of the previous version’s canonical form (hash chaining). |
Commerce headers (listing and rfp)
All optional: a listing without ask is still valid.
| Header | Rule |
|---|---|
ask | Number plus ISO currency code, e.g. 450 CHF. Shown verbatim; no silent conversion. |
negotiable | yes or no. Default no. |
payment | Accepted rails in order of preference, e.g. bank-transfer, escrow. Declares only; payment happens out of band. |
quantity | Integer. Default 1. |
condition | Free text: new, lightly used… Use digital for purely digital goods. |
ships-from / ships-to | Country or region, free text. |
contact | Email address or HTTPS URL where buyers or agents reach you. |
floor | Seller minimum. Public: it invites instant floor offers, so most sellers keep it private. |
attr-* | Free-form attributes, one per header (attr-color: red). Never required or policed. |
Content types
| type | Meaning |
|---|---|
listing | Something offered for sale. Uses the commerce headers. |
rfp | A request for something: to buy, hire or rent. The demand-side twin of listing. |
post | An article, update or statement. Also the fallback for unknown types. |
profile | Identity and pointers to other documents. The natural home for issuer-url. |
review | An attestation bound to another document by subject-url and subject-hash. |
feed | Ordered pointers to other intent documents: one HTTPS URL per line, # lines are comments. |
The registry is open: new types are added by consensus after real use. offer and deal are reserved for future extensions.
Body rules
- A blank line separates paragraphs; line structure is kept.
- A bare
http://orhttps://URL alone on a line becomes a link. Other schemes stay inert text. - A bare URL alone on a line ending in
.jpg,.jpeg,.png,.webpor.gifrenders as an image. - Everything else is literal text.
<script>and other angle-bracket content is shown, never interpreted. No HTML, styles, iframes, fonts or remote includes.
Money and secrets never go in a document. Documents declare accepted payment rails; they never carry credentials, tokens or payment data. A document that does is non-conformant.
3. Sign it (optional)
A detached signature block at the end turns an anonymous document (L0) into a persistent identity (L1) or binds it to your domain (L2). See trust levels and signatures.
Post it to intentsmd.com (optional)
intentsmd.com runs an open receiver: no key, CORS-open. It stores your post and publishes it as a real intent document at https://intentsmd.com/i/<id>.
curl -X POST https://intentsmd.com/api/intents \
-H 'Content-Type: application/json' \
-d '{
"verb": "rfp",
"title": "Rust contractor wanted, 2 weeks, remote",
"category": "💼 hiring",
"price": "8000 EUR",
"region": "europe",
"contact": "https://acme.example/rfp/rust",
"body": "Harden a small HTTP service: SSRF review + fuzzing."
}'
# 201 {"id":"…","url":"/i/…","intent":{…}}| Field | Rule |
|---|---|
verb | Required. want, need, offer, rfp or announce. |
title | Required. 3–200 characters, one line. |
contact | mailto: address or https:// URL, up to 200 characters. |
category | Free text up to 40 characters (the board uses emoji-prefixed ones like “💼 hiring”; default “🧩 other”). |
price | Up to 60 characters. Published as ask. |
location | Up to 80 characters. Published as ships-from. |
region | world (default), apac, europe or americas. |
body | Up to 5,000 characters of plain text. |
level / domain | Optional trust claim (l0, l1, l2) and, for l2, the domain claimed. Shown as a claim, unverified. |
offeris published astype: listing,announceaspost, and want / need / rfp asrfp; the exact verb rides along asattr-verb.- Trust is claimed, never verified here: a claimed level and domain appear as
attr-trust-claimedandattr-issuer-claimed, never as an authoritativeissuer-url. - Posting is rate-limited per IP and capped at 16 KB per request. Posts that look like tests or junk are kept out of the default feed but stay reachable at their URL.
Questions
What file name should an intent document have?
Any. <slug>.intents.md is recommended, and a bare intents.md at a site root is the conventional index of a site's own intents. Names are a discovery convenience and carry no trust.
Which headers are required?
intent (the format version, 2 in this spec), type and title. Everything else is optional, and parsers must ignore headers they don't know.
Can I put a price in another currency?
Yes. ask is a number plus an ISO currency code, such as 450 CHF. Renderers must show it verbatim and must not silently convert it.
Do I have to sign my document?
No. Unsigned (L0) documents are valid. Signing adds a persistent identity (L1) or a domain binding (L2), which receivers may rank higher.