API & agent documentation
Machine-readable entry points for arpitkhandelwal.com. Everything below is public, unauthenticated, and returns JSON. Agents should read llms.txt first for when-to-use guidance, then the OpenAPI document for callable operations.
Entry points
/llms.txt— Site summary and when-to-use guidance for agents./openapi.json— OpenAPI 3.1 description of every endpoint (JSON)./api/openapi.yaml— The same specification in YAML./api— Index of the public API with the operation list./sitemap.xml— Every indexable URL, with lastmod dates./robots.txt— Crawl policy. Every major AI agent is explicitly allowed.
Endpoints
| Method | Path | Operation | Returns |
|---|---|---|---|
| GET | /api/profile | getProfile | Identity, location, contact address, profile links, stack |
| GET | /api/availability | getAvailability | Booking status, reply window, sprint lengths and types |
| GET | /api/services | getServices | Focus areas, process, deliverables, terms, good and bad fits |
| GET | /api/work | listWork | Case studies and the project archive |
| GET | /api/faq | listFaq | Published questions and answers |
| POST | /api/contact | createSprintBrief | Delivers a sprint brief; replies within 24 hours |
Authentication
None. Every endpoint is public. The read endpoints are safe to call from an agent without any credential; POST /api/contact writes a message to a private inbox and should only be called when a user has explicitly asked to get in touch.
Response shape
Success responses are { "ok": true, "data": ... }. Failures are { "ok": false, "error": { "code", "message", "hint", "documentation" } } with an appropriate HTTP status. Branch on error.code, which is stable, rather than on the message text.
| Code | Meaning |
|---|---|
invalid_json | The request body could not be parsed as JSON. |
validation_failed | A field or query parameter was missing or malformed; see error.details. |
method_not_allowed | The HTTP method is not supported on this path. |
not_found | No such API endpoint. |
not_acceptable | The Accept header excluded every media type this resource can produce. |
rate_limited | Quota exhausted; wait for Retry-After seconds. |
delivery_not_configured | Contact delivery is unavailable; email directly instead. |
upstream_failure | A downstream provider failed; retry once, then email directly. |
Rate limits
Read endpoints allow 120 requests per 60 seconds per client. POST /api/contact allows 5 per 600 seconds. Every response carries RFC 9331 RateLimit and RateLimit-Policy headers, and a 429 additionally carries Retry-After in seconds. Self-throttle from those headers rather than retrying blindly.
Example
curl -s https://www.arpitkhandelwal.com/api/availability
curl -s -X POST https://www.arpitkhandelwal.com/api/contact \
-H 'content-type: application/json' \
-d '{"name":"Ada","email":"ada@example.com","message":"We need an MCP server for our internal tools in 4 weeks."}'Markdown content negotiation
Every page route honours Accept: text/markdown and responds with Vary: Accept, per acceptmarkdown.com. The same content is reachable at the .md twin of any page path, for example /about.md. A request whose Accept header excludes both text/html and text/markdown receives a 406.
Start with llms.txt for when-to-use guidance, then openapi.json for callable operations.