Overview
On the settings page, you can retrieve your organization API token to pull Swif data into 3rd party platform.
You can find your API key here:
Your API key token for Swif.ai | Help Center | Swif.ai
For general patterns and examples of using Swif APIs, see:
APIs – Manage Employees
For retrieving device applications, see:
APIs – Device Application Retrieval
For retrieving device browser extensions, see:
APIs – Device Extensions
For APIs – Team Installer Retrieval, see:
APIs – Team Installer Retrieval.
Migration and Performance Optimization
As of August 2026, the applicationInfo and extension field has been removed from the main Device Inventory API (GET /restful/organization/devices) to significantly improve performance and reduce payload sizes.
If your existing integration relies on application data, you will need to update your workflow as follows:
Retrieve Device IDs: Continue using the
/devicesendpoint to get your list of managed devices.Fetch Applications Individually: Use the
idfrom the device record to call the new dedicated endpoint:Device Application Retrieval
/restful/organization/devices/:deviceId/applications.Device Extension Retrieval
/restful/organization/devices/:deviceId/extensions
Implement Pagination: The new endpoint supports
limitandoffsetparameters, allowing you to efficiently handle devices with a large number of installed applications.
This change ensures faster response times and prevents "Repository Entity Not Found" errors that could previously occur when processing massive data payloads.
Regional Endpoints
Ensure you are using the correct base URL for your organization's data residency:
US / Global:
https://api.swifteam.comEU Tenant:
https://api.eu.swifteam.com
Team filtering and team details
You can get your organization's teams and use a team ID to see only the devices or employees in that team. Requests that don't include teamId work exactly as before, so you don't need to change existing integrations.
How it works:
Call
GET /restful/organization/teamsto get your team IDs.Add
teamId=<id>to/devicesor/employees.
List teams
GET /restful/organization/teams returns your organization's active teams, sorted by name and then by ID. It doesn't take any parameters.
CURL request
curl --location 'https://api.swifteam.com/restful/organization/teams' \
--header 'Authorization: Bearer {TOKEN}'
Sample JSON response
{
"records": [
{ "teamId": "6667d7c93300001200972f03", "teamName": "Engineering" },
{ "teamId": "68a71f053000001f00873d00", "teamName": "QA" }
],
"meta": {
"totalCount": 2,
"resultCount": 2,
"haveMore": false
}
}Field | Type | Description |
| string | The team's ID (24 hexadecimal characters) |
| string (optional) | The team's name |
Filter devices by team
Add the optional teamId parameter to GET /restful/organization/devices. You can still use q, offset (default 0) and limit (default 10) with it.
CURL request
curl --location 'https://api.swifteam.com/restful/organization/devices?teamId=6667d7c93300001200972f03&offset=0&limit=10' \
--header 'Authorization: Bearer {TOKEN}'
When you filter by team, you only get that team's devices. The meta counts include only the matching devices.
Filter employees by team
GET /restful/organization/employees also takes the optional teamId parameter, and works with q, offset and limit the same way. The filter only looks at each employee's primary team.
curl --location 'https://api.swifteam.com/restful/organization/employees?teamId=6667d7c93300001200972f03&offset=0&limit=10' \
--header 'Authorization: Bearer {TOKEN}'
Team fields in device and employee records
Each device and employee record now has two top-level fields, whether or not you filter by team:
"teamId": "6667d7c93300001200972f03",
"teamName": "Engineering"
teamName can be missing for older records whose team is no longer active.
Errors
HTTP status | Code | When it happens |
400 |
|
|
404 |
| The team doesn't exist, was deleted, or belongs to another organization |
Both errors include a friendlyMessage that you can show to users.
Device compliance
GET /restful/organization/devices now tells you whether each device is compliant and why it isn't. These are the same results the Swif webapp shows. The new fields appear on every device record, so you don't need to change your existing requests. Authentication, q, offset, limit, teamId, paging and the records/meta layout all work as before.
New fields
Field | Type | Description |
| boolean | The device's overall compliance result, the same one the webapp shows. It's |
| array of | Built-in policy checks that haven't passed. This is always an array, but it can be empty. |
| array of reason objects | Every reason the device is non-compliant, from any source (see below). It's empty for compliant devices. |
Reason object fields
Each item in nonComplianceReasons always contains source, reason, and hint. Other fields are conditionally present depending on the source. Compliant devices return an empty nonComplianceReasons: [] array.
Field | Type | When present | Description |
| string | Always | The source category: |
| string | Always | A human-readable explanation of why the device failed compliance. |
| array of strings | Always | Remediation hints. Can be empty ( |
| string | Conditional | Present when |
| string | Conditional | Present when |
| string | Conditional | Present when |
Reason sources
Multiple reasons across different sources can appear on a single non-compliant device.
Source | When it appears | Additional fields & Behavior |
| The device is non-compliant and a built-in policy check has failed. |
|
| A supported organization customer control does not match the device. |
|
| On desktop/laptop devices (non-iOS, iPadOS, Android), an enabled organization check finds that the required password manager or antivirus application is not installed. |
|
| The device has no compliance status, or its overall verdict is |
|
Sample JSON (nonComplianceReasons)
"isCompliant": false,
"failingComplianceChecks": [
{
"policyType": "FILEVAULT_POLICY",
"hint": [
"Assign and deploy team policy FILEVAULT_POLICY to this device."
]
}
],
"nonComplianceReasons": [
{
"source": "POLICY",
"policyType": "FILEVAULT_POLICY",
"reason": "Policy [FILEVAULT_POLICY] has not passed on this device.",
"hint": [
"Assign and deploy team policy FILEVAULT_POLICY to this device."
]
},
{
"source": "CUSTOMER_CONTROL",
"controlId": "ENC-1",
"controlTitle": "Full-Disk Encryption",
"policyType": "WINDOWS_BITLOCKER_AUTO_POLICY",
"reason": "Policy [WINDOWS_BITLOCKER_AUTO_POLICY] is deployed to the device but one or more settings do not meet the requirement.",
"hint": []
},
{
"source": "APPLICATION",
"reason": "Required password manager application is not installed.",
"hint": []
},
{
"source": "COMPLIANCE_STATUS",
"reason": "Device compliance status is not available.",
"hint": []
}
]
How to read the results
Use
isCompliantfor the overall answer. UsenonComplianceReasonsto explain why a device fails, andfailingComplianceChecksfor details on each built-in policy. Don't try to work out one field from another.Always read
nonComplianceReasonsto explain a non-compliant device. A device can be non-compliant with no failing policy checks. In that casefailingComplianceChecksis empty, andnonComplianceReasonslists the failing customer control, application check or missing compliance status.Show
reasonto users. Don't rely onhintalone, because it can be empty.A device can be compliant while an encryption policy still shows as failing. If the device itself reports that it's encrypted, that counts toward the overall result.
Hints:
If a policy has no hint of its own, Swif creates one:
"Create and assign policy X for this team." means the policy hasn't been created or assigned yet.
"Assign and deploy team policy X to this device." means the policy is assigned but not deployed.
Hints written by policy authors are returned as they are.
Customer-control hints may be short labels such as "Fix Policy" or "Assign Policy", or they may be empty.
Device and evidence retrieval
CURL request
curl --location 'https://api.swifteam.com/restful/organization/devices?q=H070992XF6&offset=0&limit=1' \
--header 'Authorization: Bearer {TOKEN}'
Sample JSON response and its type
{
"records": [
{
"id": "6acfde512000002300157efb",
"isAntiVirusAppInstalled": true,
"isPasswordManagerAppInstalled": true,
"isActive": true,
"owner": {
"emails": [
"angelo@swifmssp.com"
]
},
"deviceInfo": {
"deviceName": "Angelo’s MacBook Pro",
"status": "ACTIVE",
"osVersion": "27.0.1",
"osName": "macOS",
"osBuildVersion": "26A434",
"modelName": "MacBook Pro",
"modelId": "MacBookPro18,1",
"productName": "MacBookPro18,1",
"deviceType": "Laptop",
"serialNumber": "H070992XF6",
"deviceCapacity": 994,
"availableDeviceCapacity": 282
},
"mdmDeviceInfo": {
"mdmDeviceId": "26A1B06E-639E-570D-8813-30D30F056837",
"mdm_LastEnrolledAt": "2026-10-14T19:56:01.152Z",
"mdm_LastPingAt": "2026-10-15T19:32:20.768Z",
"encryption": {
"encryptionStatus": "Encrypted",
"encryptionEnabled": true
}
},
"osQueryDeviceInfo": {
"os": {
"arch": "arm64",
"build": "26A434",
"major": "27",
"minor": "0",
"name": "macOS",
"patch": "1",
"version": "27.0.1"
},
"hardware": {
"chipType": "Apple M1 Pro",
"cpuType": "",
"currentProcessorSpeed": "",
"l2CacheCore": "",
"l3Cache": "",
"machineModel": "MacBookPro18,1",
"machineName": "MacBook Pro",
"modelNumber": "MK193LL/A",
"modelSpec": {
"colors": [
"Silver",
"Space Gray"
],
"fullName": "MacBook Pro (16-inch, 2021)",
"imageURL": "https://cdsassets.apple.com/live/7WUAS350/images/macbook-pro/macbook-pro-2021-16in.png",
"modelIdentifier": [
"MacBookPro18,1",
"MacBookPro18,2"
],
"newestOperatingSystem": "macOS Sequoia",
"partNumbers": [
"MK183xx/A",
"MK193xx/A",
"MK1A3xx/A",
"MK1E3xx/A",
"MK1F3xx/A",
"MK1H3xx/A"
],
"productYear": "2021",
"productYearInt": 2021,
"screenSize": "16-inch",
"techSpecsURL": "https://support.apple.com/en-us/111901",
"userGuideURL": "https://support.apple.com/guide/macbook-pro/welcome/2021/mac"
},
"numberProcessors": "proc 10:0:8:2",
"totalCoreCount": 10,
"performanceCoreCount": 0,
"efficiencyCoreCount": 8,
"superCoreCount": 2,
"physicalMemory": "16 GB"
},
"applicationInfo": [],
"extension": {
"chromeExtension": [],
"safariExtension": [],
"firefoxAddon": [],
"edgeExtension": [],
"ieExtension": []
},
"network": {
"macAddress": {
"bridge0": "36:65:a6:25:fa:40",
"en5": "ae:41:6f:c7:4a:70",
"anpi0": "ae:41:6f:c7:4a:8f",
"ethernet": "bc:d0:74:5a:8c:5c",
"ap1": "da:2c:cb:a3:df:e1",
"en0": "36:6e:dd:1d:fa:1e",
"en1": "36:65:a6:25:fa:40",
"wifi": "bc:d0:74:5a:8c:5c",
"en4": "ae:41:6f:c7:4a:6f",
"awdl0": "a2:90:f6:1c:2b:43",
"anpi2": "ae:41:6f:c7:4a:91",
"en6": "ae:41:6f:c7:4a:71",
"nan0": "f2:c2:20:98:c1:06",
"llw0": "a2:90:f6:1c:2b:43",
"en2": "36:65:a6:25:fa:44",
"anpi1": "ae:41:6f:c7:4a:90",
"bluetooth": "BC:D0:74:59:7F:26",
"en3": "36:65:a6:25:fa:48"
},
"localIP": "172.18.205.146",
"externalIP": "50.145.36.26"
}
},
"systemPolicy": {
"password": {
"minLength": 8,
"pinHistory": 2,
"allowSimple": true,
"maxInactivity": 0,
"maxGracePeriod": 0,
"minimumPasswordAge": 0,
"maximumPasswordAge": 180,
"minComplexChars": 1,
"maxFailedAttempts": 6,
"requireAlphanumeric": true,
"minutesUntilFailedLoginReset": 0,
"lockoutBadCount": 0,
"lockoutDuration": 0
},
"screenSaver": {
"idleTime": 900,
"askForPassword": true,
"askForPasswordDelay": 0,
"screenSaveActive": false,
"screenSaverExe": "",
"screenSaverGracePeriod": 0
}
},
"teamId": "6acfb1a82400002a00a49fa1",
"teamName": "Swif's Team",
"isCompliant": false,
"failingComplianceChecks": [
{
"policyType": "FILEVAULT_POLICY",
"hint": [
"Assign and deploy team policy FILEVAULT_POLICY to this device."
]
}
],
"nonComplianceReasons": [
{
"source": "POLICY",
"policyType": "FILEVAULT_POLICY",
"reason": "Policy [FILEVAULT_POLICY] has not passed on this device.",
"hint": [
"Assign and deploy team policy FILEVAULT_POLICY to this device."
]
},
{
"source": "CUSTOMER_CONTROL",
"controlId": "ENC-1",
"controlTitle": "Full-Disk Encryption",
"reason": "Policy [WINDOWS_BITLOCKER_AUTO_POLICY] is deployed to the device but one or more settings do not meet the requirement.",
"hint": []
}
]
}
],
"meta": {
"totalCount": 1,
"resultCount": 1,
"haveMore": false
}
}
Note: applicationInfo and extension are still in the inventory response so older integrations don't break, but they're always empty.
To get a device's applications, call
/restful/organization/devices/:deviceId/applications.
For browser extensions, call
/restful/organization/devices/:deviceId/extensions.