API Overview
2 min read
REST API endpoints, authentication, and rate limits for the Made For Law platform.
Base URL
https://portal.madeforlaw.com/api/v1Embed widgets (loader.js + embedded calculators) are hosted on:
https://app.madeforlaw.comAuthentication
Most API requests require a valid access token in the Authorization header:
Authorization: Bearer <access_token>Embeds typically authenticate via a license key (the widget loader's data-key) and receive a short-lived token automatically.
Available Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/licenses/activate |
Activate a license key |
POST |
/api/licenses/exchange |
Exchange auth code for tokens |
GET |
/api/licenses/status |
Check license status |
POST |
/api/license/activate |
Create widget embed session token |
POST |
/api/calc/estimate |
Run a calculation |
POST |
/api/pdf/generate |
Generate a PDF |
POST |
/api/billing/customer-portal |
Get billing portal URL |
Embed postMessage Events
Iframe embeds can emit browser postMessage events to the host page.
Validate event.origin === "https://app.madeforlaw.com" before using event payloads.
| Event | Description |
|---|---|
mfl-ready |
Calculator UI initialized |
mfl-resize |
Content height changed |
mfl-result |
Calculation completed |
mfl-lead |
Lead captured |
mfl-error |
Calculation/network error |
Legacy resize aliases still seen in older embeds:
mfl-embed-resizegsi-embed-resize
Rate Limits
| Endpoint | Limit |
|---|---|
| License activation | 10 requests/minute |
| Calculations | 60 requests/minute |
| PDF generation | 20 requests/minute |
| All other endpoints | 120 requests/minute |
Rate limit headers are included in every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1700000000Error Responses
All errors follow this format:
json
{
"error": {
"code": "INVALID_LICENSE",
"message": "The provided license key is invalid or expired.",
"status": 401
}
}Common error codes:
| Code | Status | Description |
|---|---|---|
INVALID_LICENSE |
401 | License key is invalid or expired |
DOMAIN_NOT_ALLOWED |
403 | Domain not in allowed list |
RATE_LIMITED |
429 | Too many requests |
INTERNAL_ERROR |
500 | Server error |
Was this page helpful?