Developer Portal
Public API documentation for East End Business Services. It's a small API with no accounts and two jobs: the contact form (POST /api/v1/contact) and takeoff orders with plan uploads (POST /api/v1/orders/upload-url and POST /api/v1/orders). Everything is documented in full below.
Authentication
None required. The API is public and unauthenticated. There is no API key to request or manage — rate limiting (next section) is applied per client IP instead of per key.
Rate limits
/api, /api/v1, /api/contact, /api/v1/contact, /api/v1/orders, and any unknown /api/* path are limited to 120 requests per 60-second window per client IP; /api/v1/orders/upload-url has a stricter limit of 20 per 60 seconds. Every response on those paths carries:
| Header | Meaning |
|---|---|
RateLimit-Limit | Quota for the current window (120) |
RateLimit-Remaining | Requests left in the current window |
RateLimit-Reset | Seconds until the window resets |
Header names follow draft-ietf-httpapi-ratelimit-headers. Exceeding the limit returns 429 with a Retry-After header (seconds): a structured JSON error, matching every other /api/* error. The homepage and static pages are not rate limited by this API.
Versioning & deprecation policy
Endpoints are versioned by URL path: the current version is v1, under /api/v1/. Unversioned /api/* paths are deprecated aliases kept working for backward compatibility.
A deprecated response carries an RFC 8594 Deprecation: true header and a Link header with rel="successor-version" pointing to its replacement. A Sunset header with a removal date is added once one is scheduled — none is scheduled today.
Endpoints
| Method | Path | Status |
|---|---|---|
| GET | /api/v1 | current |
| POST | /api/v1/contact | current |
| POST | /api/v1/orders/upload-url | current |
| POST | /api/v1/orders | current |
| GET | /api | deprecated |
| POST | /api/contact | deprecated |
Full request/response schemas: /openapi.json (OpenAPI 3.0.3).
Quickstart
List the current API surface:
curl https://eebs.us/api/v1
Submit a contact inquiry (safe to run as-is — it delivers to a real inbox, so use recognizable test data):
curl -X POST https://eebs.us/api/v1/contact \
-H "Content-Type: application/json" \
-d '{
"Nombre": "Test Agent",
"Correo": "test@example.com",
"Mensaje": "API quickstart test — please disregard."
}'
A successful submission returns 200 with {"success": true, "message": "..."}. Every error path — malformed JSON, a missing required field, an unreachable upstream — returns a structured JSON body:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required field(s): Correo.",
"resolution": "Include Nombre and Correo in the request body."
}
}
Takeoff orders
Ordering a construction takeoff is two steps. There is no online payment: East End Business Services emails a quote and invoice, and delivers 24–48 h after payment. Orders are meant for the web form at /en/order (/pedido in Spanish): they require a Cloudflare Turnstile anti-spam token that only a browser can obtain, so automated agents can't place orders — use POST /api/v1/contact instead.
1. Upload each plan PDF (application/pdf, up to 500 MB each). The first call sends a Turnstile token and gets back a ref plus an upload_token; the following files of the same order send ref + upload_token (valid 30 minutes) instead of a new token. Each call returns a 15-minute presigned URL; PUT the file body straight to it. This endpoint allows 20 requests per minute per IP.
POST /api/v1/orders/upload-url
{"filename": "plans.pdf", "content_type": "application/pdf", "size": 2048000, "turnstile_token": "…"}
→ {"ref": "w-…", "key": "web/w-…/plans.pdf", "upload_url": "https://…", "method": "PUT",
"headers": {"Content-Type": "application/pdf"}, "upload_token": "…"}
PUT {upload_url} (Content-Type: application/pdf, body = the PDF)
2. Submit the order with the ref, the uploaded keys, acepto_terminos: true (acceptance of the terms and privacy policy) and the same upload_token (or a fresh Turnstile token). tipo is one of roof, exterior, comercial, otro.
POST /api/v1/orders
{"ref": "w-…", "tipo": "roof", "nombre": "…", "email": "…", "direccion": "…", "ciudad_estado": "…",
"files": ["web/w-…/plans.pdf"], "acepto_terminos": true, "upload_token": "…", "lang": "en"}
→ {"success": true, "ref": "w-…", "pedido_id": null}
A missing or invalid token returns 403 TURNSTILE_FAILED; not accepting the terms returns 422 TERMS_NOT_ACCEPTED.
Sandbox
There is no separate sandbox environment. POST /api/v1/contact is low-risk (a contact-form relay with server-side validation) and can be exercised directly against production with clearly-labeled test data, as shown in the quickstart. POST /api/v1/orders is different: every order reaches the EEBS team and starts a real quote — submit real orders only, never test data.
Machine-readable resources
| Resource | Purpose |
|---|---|
| /openapi.json | Full OpenAPI 3.0.3 specification |
| /llms.txt | Site summary for LLM agents (llmstxt.org) |
| /sitemap.xml | XML sitemap |