Summary and recommendation
Atera exposes a REST API at https://app.atera.com/api/v3 authenticated via a single static API key passed in the X-API-KEY header. The key grants full, unscoped access to all API resources - there is no OAuth flow, no scope system, and no way to issue read-only or resource-limited keys.
API access requires a paid subscription; the 30-day free trial blocks all API calls. For teams that need pre-built, maintained connectivity across Atera and the broader identity stack, Stitchflow's MCP server with ~100 deep IT/identity integrations is the relevant alternative to evaluate against building and operating custom API logic.
API quick reference
| Has user API | Yes |
| Auth method | API Key (static token passed in X-API-KEY request header) |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | Enterprise |
Authentication
Auth method: API Key (static token passed in X-API-KEY request header)
Setup steps
- Log in to Atera and navigate to Admin > Data Management > API.
- Copy the displayed API key (one key per account; no scopes or OAuth flows).
- Include the key in every request as the HTTP header: X-API-KEY:
. - API access is not available during the free trial period; a paid subscription is required.
- To rotate the key, click 'Reset my API key' in the same Admin > API page - all requests using the old key will immediately fail.
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| ContactID | integer | System-assigned unique identifier for the contact. | auto-assigned | read-only | Required as path param for GET/PUT/DELETE on a specific contact. |
| CustomerID | integer | ID of the customer (organization) this contact belongs to. | required | required | Contacts must be associated with an existing customer. |
| Firstname | string | Contact's first name. | required | optional | |
| Lastname | string | Contact's last name. | required | optional | |
| string | Contact's email address. Used for ticket creation and portal login. | required | optional | Email must be unique per customer. Contacts without email cannot create tickets via email. | |
| Phone | string | Contact's phone number. | optional | optional | |
| JobTitle | string | Contact's job title. | optional | optional | |
| IsContactPerson | boolean | Flags the contact as the primary contact person for the customer. | optional | optional | |
| InIgnoreEmailList | boolean | When true, emails from this contact are ignored and no tickets are created. | optional | optional | Corresponds to the 'Ignore emails from contact/user' setting in the UI. |
| CustomerName | string | Name of the associated customer organization (read from customer record). | read-only | read-only | Derived from CustomerID; set on the Customer object, not the Contact. |
| AgentID | integer | System-assigned unique identifier for an agent (monitored device/endpoint). | auto-assigned | read-only | Agent objects represent devices, not human users. Separate from Contact objects. |
| MachineID | string | Machine identifier for the agent endpoint. | auto-assigned | read-only | |
| MachineName | string | Hostname of the monitored device. | auto-assigned | read-only | |
| OnlineStatus | boolean | Whether the agent/device is currently online. | read-only | read-only | |
| OperatingSystem | string | OS of the monitored device. | read-only | read-only | |
| CustomFieldName (dynamic) | string|date|number | Custom fields defined in Admin > Custom Fields for Contact, Customer, Agent, Ticket, etc. | optional | optional | Accessed via /api/v3/customvalues/agentfield/{agentId}/{fieldName}. PUT body format is poorly documented; community reports trial-and-error required. |
Core endpoints
List all contacts
- Method: GET
- URL:
https://app.atera.com/api/v3/contacts - Watch out for: Supports searchOptions.email query param for filtering by email. Contacts without an email address cannot create tickets via email.
Request example
curl -X GET 'https://app.atera.com/api/v3/contacts?page=1&itemsInPage=20' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Accept: application/json'
Response example
{
"page": 1,
"itemsInPage": 20,
"totalPages": 5,
"items": [
{"ContactID": 101, "Firstname": "Jane", "Lastname": "Doe",
"Email": "jane@acme.com", "CustomerID": 42}
]
}
Get a specific contact
- Method: GET
- URL:
https://app.atera.com/api/v3/contacts/{contactId}
Request example
curl -X GET 'https://app.atera.com/api/v3/contacts/101' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Accept: application/json'
Response example
{
"ContactID": 101,
"Firstname": "Jane",
"Lastname": "Doe",
"Email": "jane@acme.com",
"CustomerID": 42,
"Phone": "555-1234",
"JobTitle": "IT Manager"
}
Create a contact
- Method: POST
- URL:
https://app.atera.com/api/v3/contacts - Watch out for: CustomerID must reference an existing customer. Community notes that an email address is effectively required for portal/ticket functionality even if the field is technically optional.
Request example
curl -X POST 'https://app.atera.com/api/v3/contacts' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"CustomerID":42,"Firstname":"Jane","Lastname":"Doe","Email":"jane@acme.com"}'
Response example
{
"ActionID": 0,
"ArticleID": 101,
"Status": "Success"
}
Update a contact
- Method: PUT
- URL:
https://app.atera.com/api/v3/contacts/{contactId} - Watch out for: PUT is a full replacement; omitting optional fields may clear them. ContactID must be in the path; CustomerID must be in the body.
Request example
curl -X PUT 'https://app.atera.com/api/v3/contacts/101' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"Firstname":"Janet","Lastname":"Doe","Email":"janet@acme.com","CustomerID":42}'
Response example
{
"ActionID": 0,
"ArticleID": 101,
"Status": "Success"
}
Delete a contact
- Method: DELETE
- URL:
https://app.atera.com/api/v3/contacts/{contactId}
Request example
curl -X DELETE 'https://app.atera.com/api/v3/contacts/101' \
-H 'X-API-KEY: YOUR_API_KEY'
Response example
{
"ActionID": 0,
"ArticleID": 101,
"Status": "Success"
}
List all customers (organizations)
- Method: GET
- URL:
https://app.atera.com/api/v3/customers - Watch out for: Customers are organizations/tenants, not individual users. Contacts are the user-level objects nested under customers.
Request example
curl -X GET 'https://app.atera.com/api/v3/customers?page=1&itemsInPage=20' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Accept: application/json'
Response example
{
"page": 1,
"totalPages": 3,
"items": [
{"CustomerID": 42, "CustomerName": "Acme Corp", "City": "New York"}
]
}
Update a customer
- Method: PUT
- URL:
https://app.atera.com/api/v3/customers/{customerId} - Watch out for: CustomerID is required as a path parameter. The official docs note you can find the CustomerID from the URL when viewing the customer page in the UI.
Request example
curl -X PUT 'https://app.atera.com/api/v3/customers/42' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"CustomerName":"Acme Corporation","City":"New York"}'
Response example
{
"ActionID": 0,
"ArticleID": 42,
"Status": "Success"
}
List all agents (devices)
- Method: GET
- URL:
https://app.atera.com/api/v3/agents - Watch out for: Agents represent monitored endpoints/devices, not human technician accounts. Use /api/v3/agents/customer/{customerId} to filter by customer.
Request example
curl -X GET 'https://app.atera.com/api/v3/agents?page=1&itemsInPage=50' \
-H 'X-API-KEY: YOUR_API_KEY' \
-H 'Accept: application/json'
Response example
{
"page": 1,
"totalPages": 4,
"items": [
{"AgentID": 9, "CustomerID": 42, "MachineName": "DESKTOP-01",
"OnlineStatus": true, "OperatingSystem": "Windows 11"}
]
}
Rate limits, pagination, and events
- Rate limits: Atera enforces a single global rate limit of 700 requests per minute across all endpoints, regardless of plan tier. No per-endpoint or per-resource sub-limits are documented.
- Rate-limit headers: No
- Retry-After header: No
- Rate-limit notes: Official FAQ states 700 req/min. Atera recommends batching requests, implementing delays/throttling in scripts, and staggering large exports over time to avoid failures. No rate-limit response headers are documented. Atera does not provide dedicated API logs within the platform.
- Pagination method: offset
- Default page size: 20
- Max page size: 50
- Pagination pointer: page (1-based integer) and itemsInPage (number of records per page). Response envelope includes: page, itemsInPage, totalPages, totalItemCount, prevLink, nextLink, items[].
| Plan | Limit | Concurrent |
|---|---|---|
| All paid plans | 700 requests per minute | 0 |
- Webhooks available: Yes
- Webhook notes: Atera supports outbound webhooks triggered by ticket automation rules. Webhooks send HTTP POST notifications to a configured callback URL when a ticket automation rule fires. Webhooks must be created first, then assigned as an action within a ticket automation rule.
- Alternative event strategy: Webhooks are gated to Enterprise (IT Departments) and Superpower (MSP) plan tiers. Lower-tier customers must poll the REST API for changes. No alert- or agent-level webhook events are documented.
- Webhook events: New ticket created, Ticket closed/resolved, Ticket status changed
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Enterprise
- Endpoint: Not documented
Limitations:
- Atera does not offer a native SCIM 2.0 endpoint for automated user provisioning from an IdP.
- SSO (Okta, Entra ID) is available on Enterprise/Superpower tiers but SCIM provisioning is not documented as a supported feature.
- User/contact lifecycle management must be performed via the REST API (/api/v3/contacts) or manually in the UI.
- The context reference notes has_native_scim=false; no official Atera documentation contradicts this.
Common scenarios
The three primary automation scenarios supported by the API are: (1) contact provisioning - POST to /api/v3/contacts with a valid CustomerID, Firstname, Lastname, and Email. the customer record must already exist or be created first via POST /api/v3/customers.
(2) bulk contact export - paginate GET /api/v3/contacts using page (1-based) and itemsInPage (max 50), reading totalPages from the response envelope and implementing per-request delays to stay within the 700 req/min global rate limit.
(3) real-time ticket event notifications via webhook - available on Enterprise/Superpower tiers only, requiring both a configured webhook callback URL and an active ticket automation rule with a Trigger webhook action. no agent-, alert-, or contact-level webhook events are available on any tier.
Technician accounts are not manageable via the API; only end-user contacts at /api/v3/contacts are exposed.
Provision a new end-user contact under an existing customer
- GET /api/v3/customers to find the target CustomerID (or use a known ID).
- POST /api/v3/contacts with body: {CustomerID, Firstname, Lastname, Email} to create the contact.
- Verify creation by calling GET /api/v3/contacts/{contactId} using the ArticleID returned in the POST response.
Watch out for: If the customer does not exist yet, first POST /api/v3/customers to create it. Email is effectively required for the contact to submit tickets via email or the portal.
Bulk-export all contacts for a customer for reporting or migration
- GET /api/v3/contacts?page=1&itemsInPage=50 (optionally filter by searchOptions.email or customer).
- Read totalPages from the response envelope.
- Loop from page=1 to totalPages, collecting items[] from each response.
- Implement a delay between requests to stay within the 700 req/min rate limit.
Watch out for: Large exports can hit the rate limit quickly. Atera recommends staggering the export over a longer time period and implementing throttling in scripts.
Receive real-time ticket notifications via webhook (Enterprise/Superpower only)
- In Atera Admin, navigate to the Webhooks page and create a new webhook with a callback URL.
- Navigate to Admin > Support and Ticketing > Ticket Automation Rules.
- Create or edit a rule with a supported trigger (New ticket created, Ticket closed/resolved, or Ticket status changed).
- Under Actions, select 'Trigger webhook' and choose the webhook created in step 1.
- Save and activate the rule; test using the 'Test' action on the Webhooks page.
Watch out for: Both the webhook and the ticket automation rule must be active for notifications to fire. Webhooks are restricted to ticket events only - no agent, alert, or contact-level webhook events are available.
Why building this yourself is a trap
Several API behaviors create integration risk that is not obvious from the documentation. PUT on both contacts and customers is a full replacement - there is no PATCH support, and omitting optional fields in a PUT body will silently clear existing values.
Resetting the API key immediately invalidates the old key and breaks every integration using it simultaneously, with no grace period. The single-key-per-account model means a key rotation event is a global outage for all API consumers. Custom field values via /api/v3/customvalues/ have poorly documented PUT request body formats with significant community-reported trial-and-error required.
Atera provides no native API logs or audit trails, so external logging infrastructure is required for any compliance or debugging use case. Teams building on this API directly should evaluate the MCP server with ~100 deep IT/identity integrations as a baseline before committing to custom integration maintenance.
Automate Atera workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.