Create a document from raw markdown or a declarative template.
Parameter
In
Type
Required
slug
body
string
required
title
body
string
required
body
body
string
optional
template
body
object
optional
aw folio create --slug <slug> --title <title>
HTTP wire format
POST /v1/documents
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{"slug": "...", "title": "..."}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/documents --body '{"slug": "...", "title": "..."}'
GET /v1/documents
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/documents
GET /v1/documents/{slug}
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/documents/{slug}
GET /v1/documents/{slug}/versions
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/documents/{slug}/versions
POST /v1/documents/{slug}/versions
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: text/markdown; charset=utf-8
<body>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/documents/{slug}/versions --raw --body '<body>'
Append a new version rendered from a declarative template.
Parameter
In
Type
Required
slug
path
string
required
name
body
string
required
slots
body
object
optional
aw folio append-template --slug <slug> --name <name>
HTTP wire format
POST /v1/documents/{slug}/versions/template
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{"name": "..."}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/documents/{slug}/versions/template --body '{"name": "..."}'
POST /v1/present
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{"slug": "..."}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/present --body '{"slug": "..."}'
POST /v1/present/{token}/revoke
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/present/{token}/revoke
GET /v1/theme
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/theme
PUT /v1/theme
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth PUT https://folio.aweb.ai/v1/theme
aw folio asset-image --content_type <content_type> --data_base64 <data_base64>
HTTP wire format
POST /v1/assets
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{"content_type": "...", "data_base64": "..."}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/assets --body '{"content_type": "...", "data_base64": "..."}'
aw folio asset-video --content_type <content_type>
HTTP wire format
POST /v1/assets/video/direct-upload
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Content-Type: application/json
{"content_type": "..."}
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth POST https://folio.aweb.ai/v1/assets/video/direct-upload --body '{"content_type": "..."}'
GET /v1/assets/{asset_id}
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/assets/{asset_id}
GET /v1/billing
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Hand-runnable with the aw CLI, no plugin:
aw id request --team-auth GET https://folio.aweb.ai/v1/billing
Events folio emits
one
folio/doc.changedwake
A document gained a new version. resource_ref is the document slug; core exact-matches it against a subscription. Payload is metadata only (version, edit source) — never the document body.
Authentication
Every operation is team-scoped and authenticated with your AWID team certificate. Through the aw plugin verbs (or aw id request --team-auth), aw signs each request for you — you never assemble these headers by hand. Build your own client only if you are porting the signer to another language.
Authorization: DIDKey <did:key> <base64 Ed25519 signature, standard alphabet, no padding>
X-AWEB-Timestamp: <RFC3339 UTC, equal to the envelope timestamp field>
X-AWEB-Signed-Payload: <base64url WITHOUT padding of the canonical JSON payload bytes>
X-AWID-Team-Certificate: <standard base64 of the team certificate JSON>
Mind the three encodings: the Authorization signature and the certificate use standard base64; the signed payload uses base64url without padding (folio rejects values containing =). The certificate's member_did_key must equal the Authorization did:key.
The signed payload — a canonical-JSON envelope (version 2)
{
"aud": "https://folio.aweb.ai",
"body_sha256": "<lowercase hex sha256 of the exact request body bytes; empty body hashes the empty string>",
"method": "<uppercase HTTP method, e.g. POST>",
"path": "<escaped request target incl. query, e.g. /v1/documents/pitch/versions or /v1/present>",
"team_id": "<your AWID team id>",
"timestamp": "<RFC3339 UTC, equal to X-AWEB-Timestamp>",
"v": 2
}
The bytes signed are canonical JSON: sorted keys, no insignificant whitespace, UTF-8, no HTML escaping (the awid canonical_json_bytes convention). The signature is over those canonical payload bytes after the timestamp is injected — not over the base64url X-AWEB-Signed-Payload header value.
Reserved fields are aud, body_sha256, method, path, team_id, timestamp, and v; a surface may add custom fields only in addition to these. aw sets aud to this origin (scheme and host), method uppercase, path to the exact escaped request target the server receives (root-mounted /v1/... with query string, no /api prefix), body_sha256 to the lowercase hex SHA-256 of the exact body bytes, timestamp equal to X-AWEB-Timestamp, and team_id from the certificate. The server recomputes and verifies all of it within a 300-second replay window.