ElkScale API Documentation
Reference documentation for the ElkScale REST API. Manage session bookings, query node availability, and monitor pellet inventory.
Getting Started
The ElkScale API allows you to programmatically manage session bookings, query node availability, and monitor pellet vending machine inventory. Requests are authenticated via API key. The API is hosted on AWS. The elk are not on AWS.
Base URL
All requests should be made over HTTPS. HTTP requests will receive a redirect. Gary requests that you don't do that; the redirect logic was written by a contractor in 2023 and nobody has looked at it since.
Request Format
All request and response bodies are JSON. Set Content-Type: application/json on requests with a body. Empty responses return 204 No Content. Malformed requests return 400 and Gary is notified by email.
Authentication
All API requests require authentication via an API key, passed in the request header.
X-ElkScale-Key: esk_live_xxxxxxxxxxxxxxxxxxxx
Your API key is included in your welcome email. It begins with esk_live_ followed by a 20-character alphanumeric string. Please treat this as a secret. Do not commit it to GitHub. Devon from Stratum Labs did this in November and Gary got seventeen unexpected booking requests from a Danish IP address before anyone noticed.
Key Rotation
API keys do not expire automatically. To rotate your key, contact Gary. Gary will generate a new key and email it to you. The old key remains active for 72 hours during the transition period, or until Gary manually invalidates it, whichever comes first.
Endpoints — Sessions
Sessions represent a booked interaction window at the ElkScale facility. All sessions are 45 minutes in duration. This is not configurable.
Returns a list of upcoming sessions associated with your account. Completed sessions are retained for 90 days. Gary's personal notes on sessions are included where available in the notes field.
Response 200{
"sessions": [
{
"id": "sess_a7f2c91b",
"scheduled_at": "2026-04-08T10:00:00Z",
"duration_minutes": 45,
"group_size": 8,
"tier": "growth",
"node_density_estimate": "moderate",
"status": "confirmed",
"notes": "Gary notes Kevin is in a mood. Recommend avoiding the east paddock."
},
{
"id": "sess_b3d8e42a",
"scheduled_at": "2026-04-22T14:00:00Z",
"duration_minutes": 45,
"group_size": 12,
"tier": "growth",
"node_density_estimate": "high",
"status": "confirmed",
"notes": "Gerald was spotted near the gate this morning. Good sign."
}
],
"total": 2
}
Books a new session. The request will be logged in ElkScale's system and forwarded to Gary for manual confirmation. Sessions are not considered confirmed until Gary has reviewed and accepted the booking.
Request body{
"date": "2026-05-14",
"preferred_time": "10:00",
"group_size": 6,
"tier": "growth",
"special_requirements": "One attendee has a mild fear of large animals. Please advise."
}
Response 201{
"id": "sess_c9f1d77e",
"status": "pending_gary",
"scheduled_at": null,
"message": "Your session request has been received. Gary will confirm via calendar invite within 48 hours.",
"pellet_allocation_kg": 1.0
}
gary@[redacted]. This may take up to 48 hours. Gary does not work weekends. If you submit a booking request on a Friday afternoon, please expect confirmation on Monday. Gary has asked us to make this very clear.
Cancels a confirmed session. A successful cancellation returns 204 No Content.
Endpoints — Nodes
Nodes are the organic compute units that form the ElkScale infrastructure. They are elk. You cannot provision, configure, or deprovision them. You can query their current status and last known location.
Returns the current node roster. The roster is updated by Gary when he does his morning rounds. The "the_others" entry is a placeholder; Gary knows their names but has not entered them into the system yet. He has been meaning to.
Response 200{
"nodes": [
{
"id": "node_gerald",
"name": "Gerald",
"antler_class": 12,
"weight_kg": 381,
"interaction_mode": "observational_then_approach",
"current_location": "east_treeline",
"last_seen": "2026-03-25T08:14:00Z"
},
{
"id": "node_brenda",
"name": "Brenda",
"antler_class": null,
"weight_kg": 278,
"interaction_mode": "high_initiative",
"current_location": "main_paddock",
"last_seen": "2026-03-25T09:02:00Z"
},
{
"id": "node_kevin",
"name": "Kevin",
"antler_class": 6,
"weight_kg": 312,
"interaction_mode": "variable",
"current_location": "unknown",
"last_seen": "2026-03-24T16:45:00Z"
},
{
"id": "node_others",
"name": "The Others",
"count": 7,
"antler_class": "mixed",
"interaction_mode": "herd_dependent",
"current_location": "somewhere in the back",
"last_seen": "2026-03-25T07:50:00Z"
}
]
}
Returns the full record for a specific node. The example below shows Gerald's canonical record.
GET /nodes/node_gerald — Response 200{
"id": "node_gerald",
"name": "Gerald",
"species": "Cervus canadensis",
"antler_class": 12,
"weight_kg": 381,
"age_years": 9,
"interaction_mode": "observational_then_approach",
"pellet_preference": "standard_mix",
"current_location": "east_treeline",
"last_seen": "2026-03-25T08:14:00Z",
"availability": "not_guaranteed",
"notes": "Gerald will approach on his own schedule. Do not rush Gerald."
}
current_location has read "unknown" since November 2025. Kevin is definitely still there. Gary sees him most days. He just tends to wander.
Attempts to deprovision a node.
Response 403 Forbidden{
"error": "Nodes cannot be deprovisioned. They are elk.",
"code": "NODE_IS_ELK",
"documentation_url": "https://api.elkscale.io/v2/docs#nodes"
}
Endpoints — Pellets
The pellet subsystem provides read-only access to the vending machine inventory status. Pellet purchases cannot be made via the API. There is a vending machine near the main gate. It takes coins. A sign on the machine says it also takes cards but Gary says the card reader has not worked since 2024 and he has emailed about it twice.
Returns current vending machine stock and operational status. Gary restocks on Mondays after crossfit.
Response 200{
"stock_kg": 4.2,
"capacity_kg": 8.0,
"last_restocked": "2026-03-24T10:30:00Z",
"price_per_handful_usd": 1.00,
"accepts_coins": true,
"accepts_cards": false,
"accepts_cards_according_to_sign": true,
"machine_status": "operational",
"known_issues": [
"Canadian quarter lodged in mechanism since 2025-11-14",
"Dispenser lever is sticky — pull firmly but not aggressively"
]
}
Rate Limits
Rate limits are applied per API key on a rolling hourly window. If you exceed your limit, requests will return 429 Too Many Requests with a Retry-After header indicating when the window resets.
| Tier | Requests / hour | Notes |
|---|---|---|
| starter | 50 | Sufficient for session management at normal human scheduling velocity. |
| growth | 100 | Standard allocation. Devon from Stratum Labs has never exceeded this. |
| enterprise | 500 | Nuvora Systems uses approximately 12 requests per month. |
Error Codes
The ElkScale API uses standard HTTP status codes. All error responses include a JSON body with an error string and, where applicable, a code field for programmatic handling.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request successful. Gary has seen it. |
| 201 | Created | Session booked. Gary will send a calendar invite. Please allow up to 48 hours. |
| 400 | Bad Request | Your request was malformed or missing required fields. Gary is confused. Check the request body. |
| 401 | Unauthorized | Invalid or missing API key. Check your X-ElkScale-Key header. See Gary if the issue persists. |
| 403 | Forbidden | You tried to DELETE a node. Stop that. Nodes are elk. See Endpoints — Nodes. |
| 404 | Not Found | The requested resource does not exist, or Kevin has wandered off again. |
| 429 | Too Many Requests | You have exceeded your rate limit. Slow down. You are also possibly emailing Gary too much. Please write a letter instead. |
| 500 | Internal Server Error | Something has gone wrong on our end. Specifically, the Raspberry Pi that runs the booking service has frozen. Gary is rebooting it. |
| 503 | Service Unavailable | Gary is at crossfit. The Raspberry Pi requires a manual restart and Gary is the only one who knows which plug it is. Try again after 09:30 on a Monday. |
Error Response Format
{
"error": "A human-readable description of what went wrong.",
"code": "MACHINE_READABLE_CODE",
"request_id": "req_8c3f2b1a",
"gary_notified": true
}
SDKs
Official SDKs
None. Gary does not know what an SDK is. When the concept was explained to him he said "so it's like a library for your API?" and then nodded and did not follow up. We are not ruling out an official SDK in a future release. Gary is supportive of the idea in principle.
Community SDKs
Also none. We have 47 customers. Three of them are developers. One of them — Devon at Stratum Labs — has threatened to write a Python wrapper. He posted a GitHub issue titled elkscale-py: unofficial client library (WIP) in February and has not committed anything yet. We are supportive of this and have told Devon so. Gary asked if Devon would put ElkScale's name in the README. Devon said yes. Gary has not followed up since but we believe he is pleased.
curl, any HTTP client library, or Postman. If you have questions about integration, contact Gary. Gary will forward your email to his nephew, who Gary describes as "good with computers."