2. Send your first JMAP request¶
You've got a server running and a bearer token. Time to talk JMAP.
The shape of a JMAP request¶
Every JMAP call is a POST to /jmap with this envelope (RFC 8620 §3.3):
{
"using": ["urn:ietf:params:jmap:core"],
"methodCalls": [
["Core/echo", {"hello": "world"}, "c0"]
]
}
using— the capability URNs your request touches. The server rejects the request if it doesn't advertise one of them.methodCalls— an array of[methodName, args, callId]triples. Calls in the same request can reference each other's results (see step 3).
The response mirrors the request:
Try it¶
TOKEN='chl_…'
curl -s -X POST http://localhost:8000/jmap \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"using": ["urn:ietf:params:jmap:core"],
"methodCalls": [["Core/echo", {"hi": "there"}, "c0"]]
}' | jq
Core/echo is the simplest JMAP method — it returns its arguments verbatim.
Useful for testing connectivity and for examples below.
Discover what the server can do¶
GET /.well-known/jmap returns the session resource. It tells you:
- which capabilities are enabled (look at
capabilities) - which accounts your token can reach (
accounts) - the URLs to use for upload / download / push (
apiUrl,uploadUrl, …)
You'll see the four bundled capabilities:
{
"urn:ietf:params:jmap:core": { … },
"urn:ietf:params:jmap:websocket": { … },
"urn:ietf:params:jmap:blob": { … },
"urn:jmaple:notes": { … }
}
Talk to the reference notes capability¶
ACCOUNT_ID=$(curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/.well-known/jmap | jq -r '.accounts | keys[0]')
curl -s -X POST http://localhost:8000/jmap \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d "{
\"using\": [\"urn:ietf:params:jmap:core\", \"urn:jmaple:notes\"],
\"methodCalls\": [
[\"Note/set\", {
\"accountId\": \"$ACCOUNT_ID\",
\"create\": {\"n1\": {\"title\": \"Hello\", \"body\": \"world\"}}
}, \"c0\"]
]
}" | jq
You should see a created object mapping your n1 create-id to the
server-assigned id, plus the new sessionState.
Now you've used the framework. Time to add your own capability → Writing your first capability