Introduction
The SafetyAmp API can be used to access your data in the SafetyAmp platform. Currently, documentation is lagging behind the capabilities of the API - please contact our support team if the available documentation does not meet your needs.
The API is commonly used for adding and updating users/roles and dispatching audits.
Authentication
To authorize, use this code:
# Every request requires an Authorization header with your API token
curl "api_endpoint_here"
-H "Authorization: Bearer your_api_token"
Make sure to replace
your_api_tokenwith your API key.
SafetyAmp uses API keys to allow access to the API. To request an API key, please e-mail our support team.
In most cases, your API key is tied to a user profile in the SafetyAmp account and you will likely create a new user to represent the api user.
SafetyAmp expects for the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer api_key
Making Requests
Apart from including the Authorization header, there are additional headers that are required for every API request.
Required HTTP Headers
| Name | Example Value | Description |
|---|---|---|
Authorization |
Bearer api_key |
This is used to authenticate your client |
Fqdn |
your_subdomain.safetyamp.com |
This is the subdomain of the account your token is for |
User-Agent |
YourOrg/1.0 |
Give your client a descriptive user agent that is unique to your organization |
Accept |
application/json |
Dates and Time
This API will respond with dates and times in the format YYYY-mm-dd H:i:s in the UTC timezone. Most requests expect a similarly formatted string also in UTC. Be sure to send datetime strings in UTC in this format.
Pagination Query Parameters
On list endpoints that support pagination, the following parameters are generally available.
| Parameter | Default | Description |
|---|---|---|
| limit | 25 | The number of results per request |
| page | 0 | The number of pages to offset the results by |
Rate Limit
To avoid receiving 429 - Too Many Requests error responses, ensure your client sends no more than 60 api calls per minute.
Filtering, Sorting, and Includes
List endpoints accept a standard request envelope for narrowing, ordering, and expanding the returned data. Each endpoint advertises which keys it supports for filtering, sorting, and including related resources.
# Filter utility bills to a single billing month, sort by period date, and
# include the related utility account and line items.
curl -G "https://api.safetyamp.com/api/utility_bills" \
-H "Authorization: Bearer ..." \
--data-urlencode 'filter_groups[0][filters][0][key]=billing_year' \
--data-urlencode 'filter_groups[0][filters][0][operator]=eq' \
--data-urlencode 'filter_groups[0][filters][0][value]=2025' \
--data-urlencode 'filter_groups[0][filters][1][key]=billing_month' \
--data-urlencode 'filter_groups[0][filters][1][operator]=eq' \
--data-urlencode 'filter_groups[0][filters][1][value]=3' \
--data-urlencode 'sort[0][key]=period_date' \
--data-urlencode 'sort[0][direction]=desc' \
--data-urlencode 'includes[]=utility_account' \
--data-urlencode 'includes[]=line_items'
Filters
Filters are grouped under filter_groups[N][filters][M]. Each filter is an object with key, operator, and value. Filters within a group are combined with AND by default; pass filter_groups[N][or]=true to combine with OR instead.
| Operator | Description |
|---|---|
eq |
Equal to |
neq |
Not equal to |
in |
Value matches any item in a comma-separated or array value |
gt, gte |
Greater than (or equal) |
lt, lte |
Less than (or equal) |
Only the keys advertised by an endpoint may be used; unknown keys return 422 Unprocessable Entity.
Sorting
Sort entries are objects with key and optional direction (asc or desc, default asc):
sort[0][key]=period_date&sort[0][direction]=desc
Only the keys advertised by an endpoint are accepted.
Includes
includes[] expands related resources inline in the response. Endpoints document the include keys they support (e.g. utility_account, line_items.meter). Nested relations are addressed with dot notation.
Sites
Sites are physical locations of plants and facilities.
Get All Sites
curl "https://api.safetyamp.com/api/sites"
-H "Authorization: Bearer ..."
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"name": "Hybrid Plant - Austin, TX",
"street": "111 Paradise Lane",
"street2": null,
"city": "Austin",
"state": "TX",
"zip_code": "11111",
"country": "USA",
"latitude": "",
"longitude": "",
"naics_code": null,
"industry_description": "",
},
...
]
}
This endpoint retrieves all sites.
HTTP Request
GET https://api.safetyamp.com/api/sites
Get a Specific Site
curl "GET https://api.safetyamp.com/api/sites/1"
-H "Authorization: Bearer ..."
Refer to list endpoint for response
This endpoint retrieves a specific site.
HTTP Request
GET https://api.safetyamp.com/api/sites/<id>
URL Parameters
| Parameter | Description |
|---|---|
| id | The id of the site to retrieve |
Roles
SafetyAmp implements role based access control. Users are assigned to multiple roles and receive aggregate permissions from their combined roles.
Get All Roles
curl "https://api.safetyamp.com/api/roles"
-H "Authorization: Bearer ..."
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"name": "Plant Manager"
},
...
]
}
This endpoint retrieves all roles.
HTTP Request
GET https://api.safetyamp.com/api/roles
Titles
SafetyAmp maintains a set of titles for your company. Users can be assigned one of these.
Get All Titles
curl "https://api.safetyamp.com/api/user_titles"
-H "Authorization: Bearer ..."
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"name": "Plant Assitant Manager"
},
...
]
}
This endpoint retrieves all titles.
HTTP Request
GET https://api.safetyamp.com/api/user_titles
Users
Creating a User
This endpoint allows the creation of new users in your account.
curl -X POST "https://api.safetyamp.com/api/users" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d` {
"first_name": "Jane",
"middle_name": null,
"last_name": "Doe",
"nickname": null,
"gender": "1",
"email": "jane.doe@example.com",
"date_of_birth": "1999-01-31",
"street": "11 Paradise Ln",
"street2": null,
"city": "San Francisco",
"state": "CA",
"zip_code": "94131",
"country":"US",
"mobile_phone": "+11231231234",
"home_phone": "+12342342345",
"work_phone": "+13453453456",
"pending":1,
"system_access":1,
"bypass_sso":0,
"text_opt_out": 0,
"text_opt_out":0,
"timezone":"America/New_York",
"roles":[{"id": 1}],
"home_site_id": 1,
"sites":[{"id": 1}],
"current_title_id":1,
"current_department_id":1,
"current_supervisor_id":1
}`
HTTP Request
POST https://api.safetyamp.com/api/users
Request Body
| Parameter | Description |
|---|---|
| first_name | (Required) The first name of the user |
| last_name | (Required) The last name of the user |
| (Required) The email address of the user, must be unique, currently used as username | |
| mobile_phone | Integers only, used for SMS messaging if provided |
| system_access | 1 if user can login to SafetyAmp, 0 if user cannot |
| pending | Boolean, a user input with pending as true will not send Activation email on create |
| activated | Set to 1 to activate user bypassing email validation |
| bypass_sso | If SSO enabled for account, set to 1 to allow user to login without SSO |
| text_opt_out | 1 if user does not wish to receive SMS on mobile number |
| timezone | chosen from list of timezones in Object Reference |
| roles[] | An array of objects containing id properties of the roles to assign to the user |
| home_site_id | uses the id property of the site the user is primarily at. This will automatically be added to sites for site access |
| sites[] | An array of objects containing the id property of the sites that user is allowed access to |
Getting All Users
curl "https://api.safetyamp.com/api/users"
-H "Authorization: Bearer ..."
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"first_name": "Jane",
"middle_name": null,
"last_name": "Doe",
"nickname": null,
"date_of_birth": 1999-01-31,
"owner": true,
"email": "jane.doe@example.com",
"work_phone": null,
"home_phone": null,
"mobile_phone": null,
"avatar_location": null,
"activated": 1,
"gender": null,
"street": "11 Paradise Ln",
"city": "San Francisco",
"state": "CA",
"zip_code": "94131",
"country": "USA",
"street2": null,
"text_opt_out": 0,
"system_access": 1,
"timezone": "America/Los_Angeles",
"home_site_id": 1,
"last_logged_in": "2019-10-25 21:40:22",
"current_title": null,
"deleted_at": null
},
...
]
}
HTTP Request
GET https://api.safetyamp.com/api/users
This endpoint supports pagination.
Getting a Specific User
curl "GET https://api.safetyamp.com/api/users/1"
-H "Authorization: Bearer ..."
Refer to list endpoint for response
HTTP Request
GET https://api.safetyamp.com/api/users/<id>
URL Parameters
| Parameter | Description |
|---|---|
| id | The id of the user to retrieve |
Updating a User
curl -X PUT "https://api.safetyamp.com/api/users/<id>" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com"
}`
HTTP Request
PUT https://api.safetyamp.com/api/users/<id>
URL Parameters
first_name, last_name, and email are required fields on PUT calls. Refer to creating a user for list of additional parameters that can be updated. Only provided values will be updated.
Remove a User
Removing a user inactivates their user account and does not allow the user to access the SafetyAmp platform. The user data will be retained.
curl -X DELETE "https://api.safetyamp.com/api/users/<id>" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
HTTP Request
DELETE https://api.safetyamp.com/api/users/<id>
URL Parameters
| Parameter | Description |
|---|---|
| id | The id of the user to retrieve |
SiteSense
SiteSense is SafetyAmp's energy management module. It tracks utility accounts (the relationship between a site and a utility provider), the meters attached to those accounts, and the bills (invoices) recorded against them. PDF copies of invoices are stored as attachments on the bill.
Permissions
SiteSense endpoints require one of two permissions:
| Permission | What it grants |
|---|---|
InvoiceViewer |
Read-only access to utility accounts and bills. Account access is scoped to the user's accessible sites. |
EnergyAdministrator |
Full read/write access to all SiteSense resources. |
Endpoints that require EnergyAdministrator are noted on each section below.
Utility Types
Utility types are the categories of utility tracked by SiteSense (e.g. electricity, natural gas, water). The set of types is managed by SafetyAmp and cannot be created, updated, or deleted via the API.
List Utility Types
curl "https://api.safetyamp.com/api/utility_types" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"name": "Electricity",
"slug": "electricity",
"unit_consumption": "kWh",
"unit_demand": "kW"
},
{
"id": 2,
"name": "Natural Gas",
"slug": "natural-gas",
"unit_consumption": "therm",
"unit_demand": null
}
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_types
This endpoint supports pagination.
Get a Utility Type
curl "https://api.safetyamp.com/api/utility_types/1" \
-H "Authorization: Bearer ..."
Refer to list endpoint for response
HTTP Request
GET https://api.safetyamp.com/api/utility_types/<id>
URL Parameters
| Parameter | Description |
|---|---|
| id | The id of the utility type to retrieve |
Utility Accounts
A utility account represents a single account a site holds with a utility provider. Bills are recorded against accounts.
Requires InvoiceViewer or EnergyAdministrator. Users without EnergyAdministrator only see accounts at sites they have access to.
List Utility Accounts
curl "https://api.safetyamp.com/api/utility_accounts" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 12,
"site_id": 1,
"provider_ref": "ACCT-44123",
"provider_name": "Austin Energy",
"type": "delivery",
"linked_to": null,
"notes": null,
"start_date": "2024-01-01",
"is_excluded": false,
"is_closed": false,
"integration_type": null,
"integration_ext_id": null,
"integration_status": null,
"last_missing_invoice_notification": null
}
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_accounts
Filter Keys
id, provider_id, provider_name, provider_ref, site_id, type_id, is_closed, is_excluded, integration_type, integration_status
Sort Keys
site, provider_name, provider_ref
Include Keys
site, meters, linked
Get a Utility Account
curl "https://api.safetyamp.com/api/utility_accounts/12" \
-H "Authorization: Bearer ..."
Refer to list endpoint for response
HTTP Request
GET https://api.safetyamp.com/api/utility_accounts/<id>
URL Parameters
| Parameter | Description |
|---|---|
| id | The id of the utility account to retrieve |
Include Keys
site, meters, linked, default_line_items
Create a Utility Account
Requires EnergyAdministrator. Returns 409 Conflict if an account with the same site_id, provider_ref, and provider_name already exists.
curl -X POST "https://api.safetyamp.com/api/utility_accounts" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"site_id": 1,
"provider_name": "Austin Energy",
"provider_ref": "ACCT-44123",
"type": "delivery",
"start_date": "2024-01-01",
"notes": null,
"is_excluded": false,
"is_closed": false
}`
HTTP Request
POST https://api.safetyamp.com/api/utility_accounts
Request Body
| Parameter | Description |
|---|---|
| site_id | (Required) The id of the site the account belongs to |
| provider_name | (Required) Name of the utility provider, max 255 chars |
| start_date | (Required) Date the account starts tracking bills, YYYY-MM-DD |
| provider_id | Optional reference to a known utility provider record |
| provider_ref | The provider's external account number, max 255 chars |
| type | One of delivery, supply, general |
| linked_to | The id of another active utility account this one is paired with |
| is_excluded | Boolean, if true the account is excluded from energy model aggregations |
| is_closed | Boolean, if true no new bills are expected on this account |
| integration_type | arc to enable Arc integration. When set, the account is validated against Arc and tied to an Arc account id |
| meters | An array of meter objects to create on the account. See "Sync Utility Account Meters" for the shape |
Update a Utility Account
Requires EnergyAdministrator.
site_id cannot be changed after creation. If the account is configured with an integration, provider_ref and provider_name cannot be changed.
curl -X PATCH "https://api.safetyamp.com/api/utility_accounts/<id>" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"notes": "Switched to time-of-use rate in March",
"is_closed": false
}`
HTTP Request
PATCH https://api.safetyamp.com/api/utility_accounts/<id>
Request Body
All fields are optional. Same parameters as create, except site_id which is immutable. Also accepts default_line_items: an array of {utility_meter_id, type, desc} objects that fully replace the account's default line items used when creating new bills.
Delete a Utility Account
Requires EnergyAdministrator. Deleting an account also deletes any bills attached to it.
curl -X DELETE "https://api.safetyamp.com/api/utility_accounts/<id>" \
-H "Authorization: Bearer ..."
HTTP Request
DELETE https://api.safetyamp.com/api/utility_accounts/<id>
Export Utility Account Bills
Requires EnergyAdministrator. Queues a background job that produces a CSV export of all bills at a site for a given year. The response is a JobStatus resource that can be polled to check progress and retrieve the resulting file.
curl -X POST "https://api.safetyamp.com/api/utility_accounts:export" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"site": 1,
"year": 2025
}`
HTTP Request
POST https://api.safetyamp.com/api/utility_accounts:export
Request Body
| Parameter | Description |
|---|---|
| site | (Required) The id of the site to export bills for. Must have energy management enabled. |
| year | (Required) The year to export, >= 2000 |
Utility Account Meters
Meters represent the individual measurement points on a utility account. A single account can have multiple meters (e.g. main panel and a sub-panel), each tied to a utility_type.
Requires EnergyAdministrator.
List Utility Account Meters
curl "https://api.safetyamp.com/api/utility_accounts/12/meters" \
-H "Authorization: Bearer ..."
The above command returns JSON structured like this:
{
"data": [
{
"id": 88,
"name": "Main Electric Meter",
"type_id": 1,
"portfolio_mgr_id": null
}
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_accounts/<id>/meters
Sync Utility Account Meters
Requires EnergyAdministrator. This is a full sync: the request body must contain every meter that should exist on the account. Meters present on the account but absent from the payload are deleted. Meters with an id are updated; meters without one are created.
curl -X PUT "https://api.safetyamp.com/api/utility_accounts/12/meters" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `[
{ "id": 88, "name": "Main Electric Meter", "type_id": 1 },
{ "name": "Sub Panel A", "type_id": 1, "portfolio_mgr_id": "PM-1234" }
]`
HTTP Request
PUT https://api.safetyamp.com/api/utility_accounts/<id>/meters
Request Body
Each item in the array supports:
| Parameter | Description |
|---|---|
| id | The id of an existing meter on this account. Omit to create a new meter. |
| name | (Required when creating) The display name, max 255 chars |
| type_id | (Required when creating) The id of a utility_type |
| portfolio_mgr_id | Optional ENERGY STAR Portfolio Manager id, max 255 chars |
Utility Bills
Utility bills (also called invoices) represent a single billing period on a utility account. Each bill carries one or more line items (usage, demand, or charges) and optionally one or more PDF attachments.
Requires InvoiceViewer or EnergyAdministrator. Users without EnergyAdministrator only see bills at sites they have access to.
List Utility Bills
curl "https://api.safetyamp.com/api/utility_bills" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json"
The above command returns JSON structured like this:
{
"data": [
{
"id": 4801,
"import_ref": null,
"import_src": null,
"utility_account_id": 12,
"billing_year": 2025,
"billing_month": 3,
"period_date": "2025-02-15",
"period_days": 30,
"currency": "USD",
"total_charges": 1842.55,
"flags": [],
"flags_silenced": false,
"unavailable": false,
"created_at": "2025-04-01 12:00:00",
"updated_at": "2025-04-01 12:00:00"
}
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_bills
Filter Keys
id, utility_account_id, billing_year, billing_month
Sort Keys
period_date
Include Keys
site, attachments, utility_account, line_items, line_items.meter
Response Fields
| Field | Description |
|---|---|
| id | The bill identifier |
| utility_account_id | The id of the account this bill belongs to |
| billing_year | Calendar year the bill covers |
| billing_month | Calendar month the bill covers, 1-12 |
| period_date | First day of the billing period, YYYY-MM-DD |
| period_days | Length of the billing period in days |
| currency | One of USD, BSD, CAD, CRC, EUR, GBP, MXN, PAB, SEK |
| total_charges | The sum of Charge line items in the bill's currency |
| flags | An array of automated validation flags raised against this bill |
| flags_silenced | Boolean, whether the flags were silenced by an admin |
| unavailable | Boolean, true if the bill is recorded as known-missing for the period (placeholder; cannot have line items or attachments) |
| import_ref | External id from the source system when the bill was imported. Cleared automatically if any non-flags_silenced field is updated. |
| import_src | Name of the source system the bill was imported from |
Get a Utility Bill
curl "https://api.safetyamp.com/api/utility_bills/4801" \
-H "Authorization: Bearer ..."
Refer to list endpoint for response
HTTP Request
GET https://api.safetyamp.com/api/utility_bills/<id>
Include Keys
site, attachments, utility_account, utility_account.meters, line_items, line_items.meter, creator, updater
Create a Utility Bill
Requires EnergyAdministrator.
curl -X POST "https://api.safetyamp.com/api/utility_bills" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"utility_account_id": 12,
"billing_year": 2025,
"billing_month": 3,
"period_date": "2025-02-15",
"period_days": 30,
"currency": "USD",
"items": [
{ "type": 1, "meter_id": 88, "desc": "Usage", "value": 12450 },
{ "type": 3, "meter_id": null, "desc": "Amount Due", "value": 1842.55 }
]
}`
HTTP Request
POST https://api.safetyamp.com/api/utility_bills
Request Body
| Parameter | Description |
|---|---|
| utility_account_id | (Required) The id of the account this bill belongs to |
| billing_year | (Required) Calendar year, integer |
| billing_month | (Required) Calendar month, integer 1-12 |
| period_date | (Required) First day of the billing period, YYYY-MM-DD |
| period_days | (Required) Length of the billing period in days, integer ≥ 1 |
| currency | (Required) Three-letter currency code (see list endpoint) |
| items | An array of line items. See "Sync Utility Bill Line Items" for the shape. Prohibited if unavailable is true. |
| flags_silenced | Boolean, silences automated validation flags on creation |
| unavailable | Boolean, mark the bill as known-missing. The bill cannot have line items or attachments. |
A 422 is returned if the new bill overlaps an existing unavailable bill on the same account/period.
Update a Utility Bill
Requires EnergyAdministrator. The utility_account_id is immutable. Bills with unavailable=true cannot be updated.
curl -X PATCH "https://api.safetyamp.com/api/utility_bills/<id>" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `{
"period_days": 31,
"items": [
{ "id": 1, "type": 1, "meter_id": 88, "desc": "Usage", "value": 12500 }
]
}`
HTTP Request
PATCH https://api.safetyamp.com/api/utility_bills/<id>
Request Body
All fields optional. Same parameters as create, except utility_account_id. If any field other than flags_silenced is updated, the bill's import_ref and import_src are cleared.
Delete a Utility Bill
Requires EnergyAdministrator. Also removes any PDF attachments on the bill.
curl -X DELETE "https://api.safetyamp.com/api/utility_bills/<id>" \
-H "Authorization: Bearer ..."
HTTP Request
DELETE https://api.safetyamp.com/api/utility_bills/<id>
Utility Bill Line Items
A bill's line items break down its usage, demand, and charges, optionally tied to a specific meter.
List Utility Bill Line Items
curl "https://api.safetyamp.com/api/utility_bills/4801/line_items" \
-H "Authorization: Bearer ..."
The above command returns JSON structured like this:
{
"data": [
{ "id": 1, "meter_id": 88, "desc": "Usage", "type": 1, "value": 12450 },
{ "id": 2, "meter_id": 88, "desc": "Peak Demand", "type": 2, "value": 42.1 },
{ "id": 3, "meter_id": null, "desc": "Amount Due", "type": 3, "value": 1842.55 }
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_bills/<id>/line_items
Line Item Types
| Value | Type | Notes |
|---|---|---|
| 1 | Usage | Quantity of the metered utility consumed (e.g. kWh) |
| 2 | Demand | Peak demand for the period (e.g. kW) |
| 3 | Charge | Monetary amount in the bill's currency |
Line items without a meter_id (ad-hoc lines) must have type = 3 (Charge).
Sync Utility Bill Line Items
Requires EnergyAdministrator. A full sync: the array supplied replaces the bill's line items entirely.
curl -X PUT "https://api.safetyamp.com/api/utility_bills/4801/line_items" \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d `[
{ "id": 1, "type": 1, "meter_id": 88, "desc": "Usage", "value": 12500 },
{ "type": 3, "meter_id": null, "desc": "Late Fee", "value": 25.00 }
]`
HTTP Request
PUT https://api.safetyamp.com/api/utility_bills/<id>/line_items
Request Body
Each item in the array supports:
| Parameter | Description |
|---|---|
| id | The id of an existing line item. Omit to create a new one. |
| type | (Required) One of 1 (Usage), 2 (Demand), 3 (Charge). Ad-hoc lines (meter_id=null) must use 3. |
| desc | (Required) Description, max 255 chars |
| meter_id | The id of a meter on this bill's account, or null for ad-hoc charges |
| value | Numeric value, up to 4 decimal places |
Utility Bill Attachments
PDFs (and other files) attached to a utility bill are exposed via short-lived signed URLs. To download an attachment:
- Call
GET /api/utility_bills/<id>/attachmentsto list attachments on the bill, orGET /api/utility_bills/<id>/attachments/<attachment_id>for a single one. - The response contains a
temporary_urlfield. Issue aGETagainst that URL to download the file. - The signed URL expires; re-request the attachment to obtain a fresh URL if needed.
List Utility Bill Attachments
curl "https://api.safetyamp.com/api/utility_bills/4801/attachments" \
-H "Authorization: Bearer ..."
The above command returns JSON structured like this:
{
"data": [
{
"id": 901,
"file_name": "invoice-2025-03.pdf",
"display_name": "March 2025 Invoice",
"file_size": 184320,
"mime_type": "application/pdf",
"type": "default",
"description": null,
"private": false,
"external_url": null,
"temporary_url": "https://storage.safetyamp.com/...signed...",
"created_at": "2025-04-01 12:00:00",
"updated_at": "2025-04-01 12:00:00"
}
]
}
HTTP Request
GET https://api.safetyamp.com/api/utility_bills/<id>/attachments
Get a Utility Bill Attachment
curl "https://api.safetyamp.com/api/utility_bills/4801/attachments/901" \
-H "Authorization: Bearer ..."
Refer to list endpoint for response
HTTP Request
GET https://api.safetyamp.com/api/utility_bills/<id>/attachments/<attachment_id>
A 404 is returned if the attachment is not attached to the specified bill.
Upload a Utility Bill Attachment
Requires EnergyAdministrator. Bills marked unavailable=true cannot have attachments. Uploads are sent as multipart/form-data with a single attachment file field.
curl -X POST "https://api.safetyamp.com/api/utility_bills/4801/attachments" \
-H "Authorization: Bearer ..." \
-F "attachment=@invoice-2025-03.pdf"
Refer to list endpoint for response
HTTP Request
POST https://api.safetyamp.com/api/utility_bills/<id>/attachments
Request Body (multipart)
| Parameter | Description |
|---|---|
| attachment | (Required) The file to upload |
Delete a Utility Bill Attachment
Requires EnergyAdministrator.
curl -X DELETE "https://api.safetyamp.com/api/utility_bills/4801/attachments/901" \
-H "Authorization: Bearer ..."
HTTP Request
DELETE https://api.safetyamp.com/api/utility_bills/<id>/attachments/<attachment_id>
A 404 is returned if the attachment is not attached to the specified bill.
Object Reference
User
{
"data": {
"id": "6Q4N8",
"owner": false,
"current_supervisor_id": null,
"current_department_id": null,
"email": "chris+conf-homer@safetyamp.com",
"work_phone": "(345)345-3456",
"home_phone": "(234)234-2345",
"mobile_phone": "(123)123-1234",
"avatar_location": null,
"created_at": "2019-10-26 15:37:13",
"created_by": "nRAzE",
"updated_at": "2019-10-26 15:37:13",
"updated_by": "nRAzE",
"deleted_at": null,
"deleted_by": null,
"last_name": "Simpson",
"date_of_birth": "1994-04-15",
"gender": 1,
"street": "street",
"city": "city",
"state": "state",
"zip_code": "24477",
"country": "US",
"timezone": "America/New_York",
"mailing_address_same_as_physical": 0,
"mailing_street": "street2",
"mailing_street2": "apt 22",
"mailing_city": "city2",
"mailing_state": "state2",
"mailing_zip_code": "24472",
"mailing_country": "US2",
"current_title_id": null,
"current_hire_date": null,
"current_employee_status_id": null,
"street2": "apt 20",
"first_name": "Homer",
"middle_name": null,
"nickname": null,
"activated": 0,
"system_access": 1,
"bypass_sso": 0,
"text_opt_out": 0,
"home_site_id": null,
"last_logged_in": null,
"remember_me": 0,
"rate_limit": null,
"constructed_permissions": [],
"current_title": null,
"preferences": null,
"roles": [],
"active_policies": [],
"eligibility_events": [],
"module_permissions": [],
"current_department": null,
"current_supervisor": null,
"sites": [],
"current_status": null,
"permissions": []
}
}
User Format
| Key | Type | Description |
|---|---|---|
| string | The email address of the user (also, the username) | |
| first_name | string | The first name of the user |
| middle_name | string | The middle name of the user |
| last_name | string | The last name of the user |
| owner | boolean | True if the user is the designated account owner |
| home_site_id | int | Id of users home site, controls record access |
| sites | array[] | Ids of sites user should have access to |
| roles | array[] | Ids of roles user should be given, controls system access |
| current_supervisor_id | int | The id of the users supervisor |
| current_department_id | int | The id of the users department |
| current_title_id | int | The id of the users title |
| mobile_phone | string | The users mobile phone number - SafetyAmp can send SMS |
| work_phone | string | The users work phone number |
| home_phone | string | The users home phone number |
| gender | int | 0 for male, 1 for female |
| street | string | User Address: Street address |
| street2 | string | User Address: Street address 2 |
| city | string | User Address: City |
| state | string | User Address: State or Province |
| zip_code | string | User Address: Postal Code |
| country | string | User Address: Country |
| activated | int | 1 for activated, 0 for not activated |
| system_access | int | 1 if the user is allowed the ability to login |
| bypass_sso | int | If SSO enabled for account, set to 1 to allow user to login without SSO |
| text_opt_out | int | 1 if user does not wish to receive SMS on mobile number |
| last_logged_in | string | The time the user last used credentials to login, does not represent last activity in the system |
Timezones
You can find a complete list of supported timezone strings (.e.g, America/New_York) by inspecting any timezone drop-down menu in the SafetyAmp web application.
Errors
The SafetyAmp API uses the following error codes:
| Error Code | Meaning |
|---|---|
| 400 | Bad Request -- Your request is invalid. |
| 401 | Unauthorized -- Your API key is wrong. |
| 403 | Forbidden -- You do not have access to the requested resource |
| 404 | Not Found -- The specified resource could not be found. |
| 405 | Method Not Allowed -- You tried to access an object with an invalid method. |
| 422 | Unprocessable Entity -- Your request is syntactically correct but one or more fields are incorrect. |
| 429 | Too Many Requests -- You've submitted more requests than the rate limit. |
| 500 | Internal Server Error -- We had a problem with our server. Try again later. |
| 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |