Guide
Manage devices
Import SIMs, assign them to customers, activate them in bulk, confirm the provider's answer and handle refusals.
A device is one SIM card, identified by its ICCID (19 or 20 digits) and IMSI (15 digits). You can also store its modem's IMEI and an external_id of your own, such as a vehicle or asset number, to find it later.
The device lifecycle
pending while the network provider confirms it. Suspended devices can be activated again; terminated is final.| Action | From | To |
|---|---|---|
| Activate | inventory, suspended | active |
| Suspend | active | suspended |
| Deactivate | active, suspended | terminated (final) |
| Delete | inventory only | (removed) |
A pending device refuses every other change until the provider answers.
Import SIMs
Import up to 5,000 SIMs at a time from CSV text with the header iccid,imsi,imei,external_id.imei and external_id are optional, and the columns can come in any order.
iccid,imsi,imei,external_id
8999001234000020718,901880000010001,356938035643809,trailer-207
8999001234000011428,901880000010002,,trailer-114
8999001234000003185,901880000010003,,reefer-031curl -X POST https://api.houndsat.com/api/json/devices/import \
-H "Authorization: Bearer $HOUNDSAT_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-d "$(jq -n --rawfile csv sims.csv '{data: {csv: $csv}}')"{
"created": [
{ "row": 2, "id": "5f0c2b7e-8d41-4a96-b3e2-91c7d0a4e6f8", "iccid": "8999001234000020718" },
{ "row": 4, "id": "0b6d4e2a-1c9f-4a3b-8e5d-7f2c0a9b6d13", "iccid": "8999001234000003185" }
],
"skipped": [
{ "row": 3, "iccid": "8999001234000011428", "reason": "already imported" }
],
"errors": []
}Every valid row is imported; rows whose ICCID or IMSI already exists are skipped, so re-running an import is safe; invalid rows are listed in errors with their row number (the header is row 1). Add "customer_id" next to "csv" to import straight into one of your customers. For a single SIM, use Add a device.
Assign to customers
Imported SIMs sit in your inventory until you assign them. Assign one, or up to 500 with Reassign devices in bulk; "customer_id": null returns a device to your inventory.
curl -X PATCH https://api.houndsat.com/api/json/devices/5f0c2b7e-8d41-4a96-b3e2-91c7d0a4e6f8/assign \
-H "Authorization: Bearer $HOUNDSAT_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "device",
"id": "5f0c2b7e-8d41-4a96-b3e2-91c7d0a4e6f8",
"attributes": {"customer_id": "c41e9a03-6b2f-4d8e-a571-0f3b9c2d7e14"}
}
}'Activate and confirm
Activate up to 500 devices per request:
curl -X POST https://api.houndsat.com/api/json/devices/bulk/activate \
-H "Authorization: Bearer $HOUNDSAT_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-d '{"data": {"ids": ["5f0c2b7e-8d41-4a96-b3e2-91c7d0a4e6f8", "0b6d4e2a-1c9f-4a3b-8e5d-7f2c0a9b6d13"]}}'Each accepted device answers "status": "ok" in the results and moves to pending at once. HoundSat then asks the network provider and settles the device when it answers, usually within seconds. To see the outcome, read the devices again, or list those still pending:
curl -g "https://api.houndsat.com/api/json/devices?filter[status]=pending&fields[device]=iccid,status,pending_operation" \
-H "Authorization: Bearer $HOUNDSAT_TOKEN"When the provider refuses
A refused or failed change puts the device back in its previous status and records why, with a message you can show as is:
{
"status": "inventory",
"last_failed_operation": "activate",
"last_error_code": "provider_rejected",
"last_error_message": "Activation failed: the provider rejected the request. Check the ICCID and try again.",
"last_error_at": "2026-10-12T14:03:24Z",
…
}last_error_code | Meaning |
|---|---|
provider_rejected | The provider refused the change. Check the ICCID and try again. |
provider_timeout | No answer in time. The change may still happen: read the device later before retrying. |
provider_rate_limited | The provider is limiting requests. Try again in a few minutes. |
provider_account_disabled | The SIM's provider account is disabled. Contact HoundSat support. |
provider_not_configured | The SIM's network isn't connected yet. Contact HoundSat support. |
provider_error | Any other provider error. |
The error fields clear when the next change starts. Separately, provider_status_mismatch turns true when an hourly check finds the provider reporting a different state than status.
Suspend and deactivate
Suspend pauses an active SIM; activate it again to resume. Deactivate ends it for good: the device becomes terminated and can't be activated again. Both work one device at a time (PATCH /api/json/devices/{id}/suspend) or in bulk, and go through pending like activation.
If two changes hit the same device at once, the second answers 409 stale_record. Read the device again and decide.
Find devices
last_seen_at is when the device last sent a message, and usage_this_month_bytes its data use so far this month. Both filter and sort:
# Never heard from
curl -g "https://api.houndsat.com/api/json/devices?filter[status]=active&filter[last_seen_at][is_nil]=true" -H "Authorization: Bearer $HOUNDSAT_TOKEN"
# Heaviest users this month
curl -g "https://api.houndsat.com/api/json/devices?sort=-usage_this_month_bytes&page[limit]=10" -H "Authorization: Bearer $HOUNDSAT_TOKEN"
# Your inventory: not assigned to a customer
curl -g "https://api.houndsat.com/api/json/devices?filter[customer_id][is_nil]=true" -H "Authorization: Bearer $HOUNDSAT_TOKEN"
# By ICCID, IMSI or external ID prefix
curl -g "https://api.houndsat.com/api/json/devices?search=trailer-2" -H "Authorization: Bearer $HOUNDSAT_TOKEN"