diff --git a/public/docs/index.html b/public/docs/index.html
new file mode 100644
index 0000000..08c5c5f
--- /dev/null
+++ b/public/docs/index.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
API Documentation
+
This page lists only endpoints that are fully unauthenticated or accept an API key via Bearer token.
+
+
Unauthenticated (public) endpoints
+
+
+
GET /api/v1/directory
+
Returns all directory entries.
+
Request
+
curl -s -X GET https://astrocom.tel/api/v1/directory
+
Response (200)
+
[{"id":1,"number":4472000,"name":"Example","route":2}, ...]
+
+
+
+
GET /api/v1/directory/openBlocks
+
Returns a list of available 10k blocks (block start numbers).
+
curl -s https://astrocom.tel/api/v1/directory/openBlocks
+
[1000000,1010000, ...]
+
+
+
+
GET /api/v1/checkAvailability/:number
+
Checks availability for a 7-digit number (rounded to NXX0000). Returns available: true/false.
+
curl -s https://astrocom.tel/api/v1/checkAvailability/4472001
+
{"available":true}
+
+
+
+
GET /api/analytics
+
Public analytics (total and daily counts).
+
curl -s https://astrocom.tel/api/analytics
+
{"total":[{"tag":"apiCalls","count":123}], "daily":[{"tag":"apiCalls","tag_date":"2025-10-27","count":10}]}
+
+
+
+
GET /discord
+
Redirects to the configured Discord invite (server-side fetch from WIDGET_URL).
+
curl -i https://astrocom.tel/discord
+
+
+
+
GET /api/v1/provision/:apiKey
+
Provisioning info for a route identified by API key. Returns server/port/iax creds and block.
+
curl -s https://astrocom.tel/api/v1/provision/REPLACE_API_KEY
+
{
+ "server":"iax.example.net",
+ "port":4569,
+ "inbound_context":"from-astrocom",
+ "iax_secret":"...secret...",
+ "block":4470000,
+ "api_key":"REPLACE_API_KEY"
+}
+
Response may include "warning" if DNS IP doesn't match requester.
+
+
+
+
GET /api/v1/route/:apiKey/:ani/:number
+
Primary routing endpoint. Returns "local" or an IAX2 dial string for the callee.
+
curl -s https://astrocom.tel/api/v1/route/REPLACE_API_KEY/4472001/4473005
+
local
+-- or --
+IAX2/from-astrocom:secret@iax.example.net:4569/4473005
+
Also available as legacy query form:
+
GET /api/v1?auth=APIKEY&ani=4472001&number=4473005
+
+
+
+
+
Bearer token endpoints (Authorization: Bearer <API_KEY>)
+
+
+
PATCH /api/v1/user/update
+
Update server/port/auth/secret for the route identified by Bearer API key (used by automated scripts).
+
curl -s -X PATCH \
+-H "Authorization: Bearer REPLACE_API_KEY" \
+-H "Content-Type: application/json" \
+-d '{"server":"iax.example.net","port":4569,"auth":"from-astrocom","secret":"new-secret"}' \
+https://astrocom.tel/api/v1/user/update
+
{"message":"Updated"}
+
+
+
+
POST /api/v1/user/dir/newEntry
+
Create or update a single directory entry for the route belonging to the API key.
+
curl -s -X POST \
+-H "Authorization: Bearer REPLACE_API_KEY" \
+-H "Content-Type: application/json" \
+-d '{"number":4472005,"name":"Alice"}' \
+https://astrocom.tel/api/v1/user/dir/newEntry
+
{"message":"Created"} or {"message":"Updated"}
+
+
+
+
DELETE /api/v1/user/dir/deleteEntry/:number
+
Delete a directory entry owned by the API key's route.
+
curl -s -X DELETE -H "Authorization: Bearer REPLACE_API_KEY" https://astrocom.tel/api/v1/user/dir/deleteEntry/4472005
+
{"message":"Deleted"}
+
+
+
+
POST /api/v1/user/dir/massUpdate
+
Mass-insert/update directory entries. Body must be {"entries":[{number,name},...],"replace":true|false}.
+
curl -s -X POST \
+-H "Authorization: Bearer REPLACE_API_KEY" \
+-H "Content-Type: application/json" \
+-d '{"replace":false,"entries":[{"number":4472001,"name":"Bob"},{"number":4472002,"name":"Carol"}]}' \
+https://astrocom.tel/api/v1/user/dir/massUpdate
+
{"message":"Mass update completed"}
+
All numbers must be within the route's block range.
+
+
+
+
+
Notes:
+
+ - Bearer endpoints accept header Authorization: Bearer <API_KEY>.
+ - Unauthenticated endpoints that accept an API key in the path/query do not require Authorization header.
+ - All numeric "number" and "ani" values must be 7-digit integers (1,000,000–9,999,999) where applicable.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file