API Client Guide

Practical examples for consuming the Pony Mail Foal API programmatically. For the full endpoint reference, see API.md.


Two Access Modes

Every endpoint supports two URL patterns:

SuffixMethodBodyUse when
.jsonPOSTJSONPreferred — native Foal protocol
.luaGETQuery paramsLegacy compatibility

All examples below show both modes.


Authentication

Public lists require no authentication. For private lists or write operations, include a session cookie:

Cookie: ponymail=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Obtain the cookie by completing an OAuth flow via the web UI, then extract it from your browser's DevTools (Network tab → Request Headers).


Common Operations

List All Mailing Lists

.json (POST):

curl -s -X POST https://lists.apache.org/api/preferences.json \
  -H "Content-Type: application/json" \
  -d '{}' | jq '.lists | keys'

.lua (GET):

curl -s "https://lists.apache.org/api/preferences.lua" | jq '.lists | keys'

Returns domain → list → message count mappings.


Search a List

.json (POST):

curl -s -X POST https://lists.apache.org/api/stats.json \
  -H "Content-Type: application/json" \
  -d '{
    "list": "dev",
    "domain": "httpd.apache.org",
    "d": "lte=30d",
    "q": "mod_proxy"
  }' | jq '.hits, .emails[0].subject'

.lua (GET):

curl -s "https://lists.apache.org/api/stats.lua?list=dev&domain=httpd.apache.org&d=lte%3D30d&q=mod_proxy" \
  | jq '.hits, .emails[0].subject'

Useful Parameters

ParameterExampleEffect
d2026-06Specific month
dlte=7dLast 7 days
ddfr=2026-01-01|dto=2026-06-30Date range
q+proxy -balancerRequired/excluded terms
header_fromrbowen@apache.orgFilter by sender
header_subject[VOTE]Filter by subject
quick1Stats only (faster, no emails/threads)
emailsOnly1Emails only (no thread_struct, participants, word cloud)

Fetch a Single Email

.json (POST):

curl -s -X POST https://lists.apache.org/api/email.json \
  -H "Content-Type: application/json" \
  -d '{"id": "rt6hrlhc4cwz0bwzf4lys43cb7lz30h6"}' | jq '.subject, .from, .date'

.lua (GET):

curl -s "https://lists.apache.org/api/email.lua?id=rt6hrlhc4cwz0bwzf4lys43cb7lz30h6" \
  | jq '.subject, .from, .date'

Fetch a Thread

.json (POST):

curl -s -X POST https://lists.apache.org/api/thread.json \
  -H "Content-Type: application/json" \
  -d '{"id": "rt6hrlhc4cwz0bwzf4lys43cb7lz30h6"}' \
  | jq '.emails | length'

Use "find_parent": true to navigate from any reply up to the thread root.


Fetch Raw Email Source

.json (POST):

curl -s -X POST https://lists.apache.org/api/source.json \
  -H "Content-Type: application/json" \
  -d '{"id": "rt6hrlhc4cwz0bwzf4lys43cb7lz30h6"}'

Returns text/plain — the raw RFC 2822 message.


Download Mbox Archive

.json (POST):

curl -s -X POST https://lists.apache.org/api/mbox.json \
  -H "Content-Type: application/json" \
  -d '{"list": "dev", "domain": "httpd.apache.org", "d": "2026-06"}' \
  -o dev-2026-06.mbox

.lua (GET):

curl -s "https://lists.apache.org/api/mbox.lua?list=dev&domain=httpd.apache.org&date=2026-06" \
  -o dev-2026-06.mbox

Rate Limiting

There is no rate limiting on the API. However, be respectful:

  • Use quick=1 or emailsOnly=1 when you don't need full results
  • Cache responses where appropriate
  • Avoid tight polling loops — use the since parameter for change detection

Error Handling

StatusMeaning
200Success
400Bad request (malformed parameters)
403Forbidden (admin endpoint, insufficient permissions)
404Email/thread not found, or invalid endpoint
500Server error (check traceback setting)

Related

  • API.md — Full endpoint reference with response schemas
  • search.md — Search query syntax
  • GitHub issue #312 — API token support (not yet implemented)