MAFM REST APIv1
The MAFM (Multi-Asset Footprint Management) REST API provides programmatic access to your building operations data. Build integrations, automate workflows, and sync data between MAFM and your other systems.
Base URL: https://mafm.app/api/v1
Format: All requests and responses use JSON
CORS: Enabled for all origins
Authentication
All API requests require authentication using an API token. Tokens are created in the MAFM app
under Settings → API Tokens and must be included in the Authorization
header of every request.
Token Format
- Production:
mafm_live_prefix - Testing:
mafm_test_prefix
Making Authenticated Requests
Include your token in the Authorization header using the Bearer scheme:
curl -H "Authorization: Bearer mafm_live_abc123def456..." \
https://mafm.app/api/v1/service-requests
Token Scopes
Each token has specific scopes that control which resources it can access.
For example, a token with only service_requests:read can view service requests
but cannot create or modify them. See the Scopes Reference for a complete list.
Rate Limiting
API requests are rate limited to ensure fair usage and system stability. The default limit is 100 requests per hour per API token.
Rate Limit Headers
Every API response includes the following headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed per hour |
X-RateLimit-Remaining |
Requests remaining in current window |
X-RateLimit-Reset |
Unix timestamp when the limit resets |
Rate Limit Exceeded
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded",
"status": 429
},
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
The response includes a Retry-After header indicating how many seconds to wait before retrying.
Pagination
List endpoints return paginated results to keep responses lightweight and performant. MAFM supports both cursor-based and offset-based pagination.
Cursor-Based Pagination (Recommended)
Cursor-based pagination is more efficient and handles real-time data changes better.
Use the cursor parameter to navigate through results:
GET /api/v1/service-requests?cursor=2024-01-15T10:30:00Z&limit=25
Offset-Based Pagination
For simpler use cases, offset-based pagination is also supported:
GET /api/v1/service-requests?offset=0&limit=25
Pagination Parameters
| Parameter | Type | Description |
|---|---|---|
cursor |
string | Cursor value from previous response (cursor-based) |
offset |
integer | Number of records to skip (offset-based) |
limit |
integer | Number of records to return (default: 25, max: 100) |
Pagination Response
All paginated responses include a meta.pagination object:
{
"data": [...],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"pagination": {
"total": 142,
"limit": 25,
"has_more": true,
"next_cursor": "2024-01-15T10:30:00Z"
}
}
}
Filtering & Sorting
Most list endpoints support filtering, sorting, and searching to help you find the exact data you need.
Filtering
Filter results using query parameters that match field names:
GET /api/v1/service-requests?status=pending&priority=high
For multiple values (OR logic), use comma-separated values:
GET /api/v1/service-requests?status=pending,in_progress
Sorting
Sort results using the sort and order parameters:
GET /api/v1/service-requests?sort=created_at&order=desc
| Parameter | Values | Default |
|---|---|---|
sort |
Field name (e.g., created_at, priority) |
created_at |
order |
asc or desc |
desc |
Searching
Use the search parameter to perform full-text search across relevant fields:
GET /api/v1/service-requests?search=leaking+faucet
Search typically covers fields like title, name, description, and notes.
Error Responses
When an error occurs, the API returns a consistent error response format with an appropriate HTTP status code.
Error Format
{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"status": 404
},
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | BAD_REQUEST |
Invalid request body or parameters |
| 401 | INVALID_TOKEN |
Missing or invalid authentication token |
| 403 | INSUFFICIENT_SCOPE |
Token lacks required permissions |
| 404 | NOT_FOUND |
Requested resource not found |
| 409 | CONFLICT |
Duplicate record or conflicting state |
| 422 | VALIDATION_ERROR |
Request validation failed |
| 429 | RATE_LIMITED |
Rate limit exceeded |
| 500 | INTERNAL_ERROR |
Internal server error |
Validation Errors
Validation errors include additional details about which fields failed validation:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"status": 422,
"details": {
"title": "Title is required",
"priority": "Must be one of: low, normal, high"
}
},
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Scopes Reference
API tokens require specific scopes to access different resources. When creating a token, you can grant read-only, write, or full access to each resource type.
| Scope | Description |
|---|---|
service_requests:read |
Read service requests |
service_requests:write |
Create, update, and delete service requests |
move_requests:read |
Read move requests |
move_requests:write |
Create, update, and delete move requests |
inventory:read |
Read inventory items |
inventory:write |
Create, update, and delete inventory items |
checklists:read |
Read daily checklists |
checklists:write |
Create, update, and delete checklists |
leases:read |
Read lease records |
leases:write |
Create, update, and delete leases |
paint:read |
Read paint records |
paint:write |
Create, update, and delete paint records |
procurement:read |
Read procurement data |
procurement:write |
Create, update, and delete procurement records |
assets:read |
Read asset records |
assets:write |
Create, update, and delete assets |
time_clock:read |
Read time clock records |
time_clock:write |
Create and update time clock records |
notes:read |
Read notes |
notes:write |
Create, update, and delete notes |
reminders:read |
Read reminders |
reminders:write |
Create, update, and delete reminders |
locations:read |
Read location and building data |
locations:write |
Create, update, and delete locations |
vendors:read |
Read vendor information |
vendors:write |
Create, update, and delete vendors |
shipping:read |
Read shipment records |
shipping:write |
Create, update, and delete shipments |
documents:read |
Read documents |
documents:write |
Upload, update, and delete documents |
hr:read |
Read HR documents |
hr:write |
Create, update, and delete HR documents |
training:read |
Read training materials |
training:write |
Create, update, and delete training materials |
butts_in_seats:read |
Read desks and workspace assignment data |
butts_in_seats:write |
Create, update, and delete desks and workspace records |
users:read |
Read user profiles (read-only access) |
companies:read |
Read company information (read-only access) |
*:read |
Read access to all resources |
*:write |
Write access to all resources |
* |
Full access to all resources (read and write) |
Security Best Practice: Grant tokens the minimum scopes required for their intended use.
For example, a reporting integration only needs *:read scopes, not write access.