An activity is anything a worker clocks in to: a Job, a Work Order or a Meet Point.
All three use the same /activities endpoints. The kind field tells them apart.
| Kind | Phase Codes | Notes |
|---|---|---|
Job | Optional | Can carry a reporting type, a reporting frequency and a program close date |
WorkOrder | None | Can link to a Job (jobCode) and to one piece of equipment (equipmentCode) |
MeetPoint | At least one | Can be shown to some crews only (audience) |
Scopes: activity:read to read, activity:write to write.
Back to the index · Conventions · Errors
Every endpoint can also return 401 (no key, or a key that is not valid, revoked or
expired) and 503 (service_unavailable or instance_mismatch). The tables below list
only the other statuses.
The Activity object
GET /activities/{activityId} returns this object in record. GET /activities returns
a list of them in record.records.
| Field | Type | Description |
|---|---|---|
activityId | integer | The activity's id |
kind | string | Job, WorkOrder or MeetPoint |
companyCode | string | The company |
sourceSystem | string | The owner. See Ownership. |
code | string | Trimmed and upper case. It never changes. |
name | string | The name that crews see. The effective value: an administrator's override where one is set. |
address | string or null | The site address (effective value) |
latitude | number or null | The site point, WGS 84 degrees (effective value). latitude and longitude are both set or both null. |
longitude | number or null | See latitude |
divisionCode | string or null | The division |
timeZone | string or null | The site's IANA time zone. Null means the account's default time zone. |
isActive | boolean | False when the activity is closed |
completeStatus | string or null | Incomplete or Complete on a Work Order. The phone hides a Complete Work Order. |
jobCode | string or null | A Work Order's Job. Null on other kinds. |
isJobKnown | boolean | True when jobCode names a Job in Matrix TimeCard |
equipmentCode | string or null | A Work Order's equipment. Null on other kinds. |
isLocallyOverridden | boolean | True when an administrator overrides a field |
overridden | array of strings | The fields that an override covers |
sourceValues.name | string or null | The owner's own name, under any override |
sourceValues.address | string or null | The owner's own address |
sourceValues.latitude | number or null | The owner's own latitude |
sourceValues.longitude | number or null | The owner's own longitude |
phaseCodes[].code | string | An active Phase Code. Only active Phase Codes are listed, ordered by code. |
phaseCodes[].description | string or null | Its description |
reportingType | string or null | A Job's reporting type. See Reporting types. Always null on other kinds. |
reportingFrequency | string or null | A Job's reporting frequency. See Reporting frequencies. Always null on other kinds. |
programClosesOn | string or null | YYYY-MM-DD, the day a Job's program closes. Null while it is open. |
audience[].divisionId | integer or null | A Meet Point audience pair: the division's id |
audience[].divisionCode | string or null | The division code. Null means any division. |
audience[].payClassId | integer or null | The pay class's id |
audience[].payClassCode | string or null | The pay class code. Null means any pay class. |
geofences[].geofenceId | integer | A boundary's id. Every boundary is listed, active or not. |
geofences[].isActive | boolean | The phone uses only active boundaries |
geofences[].isPublished | boolean | The boundary has a live version, so phones use it |
geofences[].hasDraftPending | boolean | A new version waits for an administrator to publish it |
geofences[].sourceSystem | string | The boundary's owner |
geofences[].isLocallyManaged | boolean | An administrator took the boundary over. Your key cannot change it. |
updatedAt | string | ISO 8601 UTC, to the millisecond. Send it back as expectedUpdatedAt. |
audience is empty on a Job or Work Order. On a Meet Point, an empty audience means
everyone sees it.
GET /activities
Lists Jobs, Work Orders and Meet Points, ordered by code. Each record includes its active Phase Codes and its boundaries.
Scope: activity:read
Query parameters
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
kind | string | No | All three | Job, WorkOrder, MeetPoint, or a comma list | The kinds to list. Case does not matter. |
isActive | string | No | Both | true, false | Keep only active or only inactive activities |
q | string | No | Max 100 characters | Search the code, name and address. Longer text is cut to 100 characters. | |
companyCode | string | No | Max 10 characters | Keep only this company | |
divisionCode | string | No | Max 20 characters | Keep only this division | |
sourceSystem | string | No | Every owner | Max 20 characters | Keep only records that this owner holds, for example your own |
limit | integer | No | 25 | 1 to 100 | Page size |
offset | integer | No | 0 | 0 or more | Rows to skip |
all | string | No | false | true, false | true returns every match in one response, up to 10,000. Do not send limit or offset with it. |
level | integer | No | 1 | Accepted for compatibility. Any other value gets 400. |
Example request
curl "$TIMECARD_BASE_URL/activities?kind=Job&isActive=true&limit=100&offset=0" \
-H "X-API-Key: $TIMECARD_API_KEY"
Example response 200 OK
{
"status": 200,
"message": "Success: activities retrieved.",
"record": {
"total": 1,
"records": [
{
"activityId": 48213,
"kind": "Job",
"companyCode": "ACME",
"sourceSystem": "acme-erp",
"code": "J-2026-104",
"name": "Riverside Bridge Widening",
"address": "1200 River Rd, Austin, TX 78701",
"latitude": 30.2672,
"longitude": -97.7431,
"divisionCode": "PAVING",
"timeZone": "America/Chicago",
"isActive": true,
"completeStatus": null,
"jobCode": null,
"isJobKnown": false,
"equipmentCode": null,
"isLocallyOverridden": false,
"overridden": [],
"sourceValues": {
"name": "Riverside Bridge Widening",
"address": "1200 River Rd, Austin, TX 78701",
"latitude": 30.2672,
"longitude": -97.7431
},
"phaseCodes": [
{ "code": "01-100", "description": "Mobilization" },
{ "code": "02-200", "description": "Earthwork" }
],
"reportingType": null,
"reportingFrequency": null,
"programClosesOn": null,
"audience": [],
"geofences": [
{
"geofenceId": 9120,
"isActive": true,
"isPublished": false,
"hasDraftPending": true,
"sourceSystem": "acme-erp",
"isLocallyManaged": false
}
],
"updatedAt": "2026-11-03T15:04:05.123Z"
}
]
}
}
With all=true, record.total is the number of records returned.
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_failed | kind names something else, level is not 1, isActive, limit or offset is out of range, or all=true matches more than 10,000 records |
| 403 | insufficient_scope | The key does not have activity:read |
| 500 | internal_error | The activities could not be read |
GET /activities/{activityId}
Returns one Job, Work Order or Meet Point.
Scope: activity:read
Path parameters
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
activityId | integer | Yes | 1 or more | The activity's id |
Example request
curl "$TIMECARD_BASE_URL/activities/48213" \
-H "X-API-Key: $TIMECARD_API_KEY"
Example response 200 OK
{
"status": 200,
"message": "Success: activity retrieved.",
"record": {
"activityId": 48213,
"kind": "Job",
"companyCode": "ACME",
"sourceSystem": "acme-erp",
"code": "J-2026-104",
"name": "Riverside Bridge Widening",
"updatedAt": "2026-11-03T15:04:05.123Z"
}
}
The record has every field of the Activity object. It is shortened
here.
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_failed | activityId is not a positive integer |
| 403 | insufficient_scope | The key does not have activity:read |
| 404 | not_found | No activity has this id, or it is outside the key's companies |
| 500 | internal_error | The activity could not be read |
POST /activities
Creates one Job, Work Order or Meet Point, with its Phase Codes and an optional job-site boundary. Either all of it is saved or nothing is. The new record is owned by your key's source system.
Scope: activity:write. A drawn location.boundary also needs geofences:write. A
point and radius needs no extra scope. With geofences:publish, the boundary is live at
once. Without it, the boundary is a draft until an administrator publishes it.
Request body
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
kind | string | Yes | Job, WorkOrder, MeetPoint | The kind of activity | |
code | string | Yes | Max 50 characters | Your code, for example your job number. Stored trimmed and in upper case. Must be free in the company. | |
name | string | Yes | Max 100 characters | The name that crews see on the phone | |
companyCode | string | No | Max 10 characters | The company. Required when the key covers more than one company. | |
divisionCode | string | No | Max 20 characters | The division. Phase Codes copy it. | |
address | string | No | Max 300 characters | The site address | |
timeZone | string | No | Max 64 characters, IANA name | For example America/Chicago | |
phaseCodes | array | No. A Meet Point needs at least one. | Max 1,000 items | The Phase Codes. Repeats are dropped (case does not matter). Not allowed on a Work Order. | |
phaseCodes[].code | string | Yes | Max 50 characters | Trimmed only. Case and inner spaces are kept. | |
phaseCodes[].description | string or null | No | Max 200 characters | The description | |
location | object | No | The job-site boundary. Send a point and radius, or a drawn boundary. | ||
location.latitude | number | Yes, in the point form | The site point | ||
location.longitude | number | Yes, in the point form | The site point | ||
location.radiusMeters | integer | No | 201 | 1 to 1,609 | The boundary radius in metres |
location.boundary | array | Yes, in the drawn form | 3 or more points | A ring of points, open or closed. No point more than 1 mile from its centre. | |
location.boundary[].lat | number | Yes | Latitude | ||
location.boundary[].lng | number | Yes | Longitude | ||
completeStatus | string | No | Incomplete | Incomplete, Complete | Work Order only |
jobCode | string | No | Max 50 characters | Work Order only. The code of the Job that the Work Order's hours count under. | |
equipmentCode | string | No | Max 50 characters | Work Order only. Equipment of the same company and of the Work Order's division. | |
reportingType | string or null | No | null | One of reporting types | Job only |
reportingFrequency | string or null | No | null | One of reporting frequencies | Job only |
programClosesOn | string or null | No | null | YYYY-MM-DD | Job only. The day the program closes. |
audience | array | No | [] | Max 100 items | Meet Point only. Pairs of division and pay class that see the Meet Point. Empty means everyone. |
audience[].divisionCode | string or null | No | Max 20 characters | A division. Null means any. | |
audience[].payClassCode | string or null | No | Max 30 characters | A pay class. Null means any. A pair must name at least one of the two. |
Example request: a Job
curl -X POST "$TIMECARD_BASE_URL/activities" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "Job",
"companyCode": "ACME",
"code": "J-2026-104",
"name": "Riverside Bridge Widening",
"address": "1200 River Rd, Austin, TX 78701",
"divisionCode": "PAVING",
"timeZone": "America/Chicago",
"phaseCodes": [
{ "code": "01-100", "description": "Mobilization" },
{ "code": "02-200", "description": "Earthwork" }
],
"location": { "latitude": 30.2672, "longitude": -97.7431, "radiusMeters": 201 }
}'
Example request: a Job with a drawn boundary (needs geofences:write)
curl -X POST "$TIMECARD_BASE_URL/activities" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "Job",
"companyCode": "ACME",
"code": "J-2026-105",
"name": "Eastside Yard Expansion",
"divisionCode": "PAVING",
"timeZone": "America/Chicago",
"location": {
"boundary": [
{ "lat": 30.2701, "lng": -97.7460 },
{ "lat": 30.2701, "lng": -97.7400 },
{ "lat": 30.2650, "lng": -97.7400 },
{ "lat": 30.2650, "lng": -97.7460 }
]
}
}'
Example request: a Work Order
The Job and the equipment must exist first. An unknown jobCode or equipmentCode gets
400.
curl -X POST "$TIMECARD_BASE_URL/activities" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "WorkOrder",
"companyCode": "ACME",
"code": "WO-55123",
"name": "Replace hydraulic hose - EX-210",
"divisionCode": "PAVING",
"jobCode": "J-2026-104",
"equipmentCode": "EX-210",
"completeStatus": "Incomplete"
}'
Example request: a Meet Point
curl -X POST "$TIMECARD_BASE_URL/activities" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "MeetPoint",
"companyCode": "ACME",
"code": "YARD-NORTH",
"name": "North Yard",
"address": "800 Industrial Blvd, Austin, TX 78745",
"timeZone": "America/Chicago",
"phaseCodes": [{ "code": "YARD", "description": "Yard time" }],
"location": { "latitude": 30.2101, "longitude": -97.7702, "radiusMeters": 150 },
"audience": []
}'
Example response 201 Created
{
"status": 201,
"message": "Success: activity created.",
"record": {
"activityId": 48213,
"kind": "Job",
"companyCode": "ACME",
"sourceSystem": "acme-erp",
"code": "J-2026-104",
"name": "Riverside Bridge Widening",
"phaseCodes": [
{ "code": "01-100", "description": "Mobilization" },
{ "code": "02-200", "description": "Earthwork" }
],
"geofences": [
{
"geofenceId": 9120,
"isActive": true,
"isPublished": false,
"hasDraftPending": true,
"sourceSystem": "acme-erp",
"isLocallyManaged": false
}
],
"updatedAt": "2026-11-03T15:04:05.123Z"
}
}
The record has every field of the Activity object. It is shortened
here.
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_failed | The body is not valid: for example kind is missing, a Meet Point has no Phase Code, a Work Order field is sent on another kind, timeZone is unknown, the location is not plausible, jobCode or equipmentCode names nothing in the company, or companyCode is missing when the key covers several companies |
| 403 | insufficient_scope | The key does not have activity:write |
| 403 | forbidden | The key names a company other than its own, sends a drawn boundary without geofences:write, or has no source system |
| 404 | not_found | companyCode names no active company that the key can reach |
| 409 | conflict | The code is already used in the company, by any kind and owner, active or not. detail names the kind and the owner. |
| 500 | internal_error | The activity could not be created. The record can still exist. Look it up by its code before you retry. |
PATCH /activities/{activityId}
Changes only the fields that you send. code and kind cannot change. Send null to
clear an optional field. Your key can change only an activity that its own source system
owns.
Scope: activity:write. location also needs geofences:write, for a point and radius
too.
Path parameters
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
activityId | integer | Yes | 1 or more | The activity's id |
Request body
Send at least one field. An empty body gets 400.
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
expectedUpdatedAt | string | No (recommended) | ISO 8601 date-time with Z or an offset | The updatedAt that you last read. If the activity changed after that, you get 409 and nothing is saved. | |
name | string | No | Max 100 characters | The name | |
address | string or null | No | Max 300 characters | The site address | |
divisionCode | string or null | No | Max 20 characters | The division | |
timeZone | string or null | No | Max 64 characters, IANA name | Null clears it | |
isActive | boolean | No | false closes the activity. true opens it again. | ||
phaseCodes | array | No | Max 1,000 items | Replaces the whole list. A code that you leave out is deactivated, never deleted. A code that you send again is reactivated. A Meet Point must keep at least one. Not allowed on a Work Order. | |
phaseCodes[].code | string | Yes | Max 50 characters | Trimmed only | |
phaseCodes[].description | string or null | No | Max 200 characters | The description | |
location | object | No | Redraws a boundary as a new version. Send a point and radius, or a drawn boundary, as on POST /activities. | ||
location.latitude | number | Yes, in the point form | The site point | ||
location.longitude | number | Yes, in the point form | The site point | ||
location.radiusMeters | integer | No | 201 | 1 to 1,609 | The boundary radius in metres |
location.boundary | array | Yes, in the drawn form | 3 or more points | A ring of { "lat", "lng" } points. No point more than 1 mile from its centre. | |
location.boundary[].lat | number | Yes | Latitude | ||
location.boundary[].lng | number | Yes | Longitude | ||
location.geofenceId | integer | No | 1 or more | The boundary to redraw. Required when the activity has more than one boundary. Not with newFence. | |
location.newFence | boolean | No | true | Adds a separate boundary owned by your key instead of redrawing one. Not with geofenceId. | |
point | object or null | No | Sets the site point only, with no boundary change and no extra scope. Null clears it. Not with a point-form location. | ||
point.latitude | number | Yes | Latitude | ||
point.longitude | number | Yes | Longitude | ||
completeStatus | string | No | Incomplete, Complete | Work Order only | |
jobCode | string or null | No | Max 50 characters | Work Order only. Null removes the Job link. | |
equipmentCode | string or null | No | Max 50 characters | Work Order only. Null removes the equipment link. | |
reportingType | string or null | No | One of reporting types | Job only. Null clears it. | |
reportingFrequency | string or null | No | One of reporting frequencies | Job only. Null clears it. | |
programClosesOn | string or null | No | YYYY-MM-DD | Job only. Null clears it. | |
audience | array | No | Max 100 items | Meet Point only. Replaces the whole audience. [] means everyone. | |
audience[].divisionCode | string or null | No | Max 20 characters | A division | |
audience[].payClassCode | string or null | No | Max 30 characters | A pay class |
The body can also hold revert, but only an administrator can use it. A key that sends
revert gets 400.
Which boundary location redraws
| The activity has | You send | Result |
|---|---|---|
| No boundary | location | A first boundary is added |
| One boundary that your key owns | location | That boundary is redrawn |
| Several boundaries, or one that another owner holds | location with no geofenceId | 409 conflict |
| Any | location.geofenceId | That boundary is redrawn, if your key owns it and it is not locally managed |
| Any | location.newFence: true | A separate boundary is added |
Without geofences:publish, a redrawn boundary is saved as a draft version
(hasDraftPending: true) until an administrator publishes it.
Example request
curl -X PATCH "$TIMECARD_BASE_URL/activities/48213" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expectedUpdatedAt": "2026-11-03T15:04:05.123Z",
"name": "Riverside Bridge Widening - Phase 2",
"address": "1250 River Rd, Austin, TX 78701"
}'
Example response 200 OK
{
"status": 200,
"message": "Success: activity updated.",
"record": {
"activityId": 48213,
"kind": "Job",
"code": "J-2026-104",
"name": "Riverside Bridge Widening - Phase 2",
"address": "1250 River Rd, Austin, TX 78701",
"updatedAt": "2026-11-03T15:10:42.517Z"
}
}
The record has every field of the Activity object. It is shortened
here. When the values you send are already stored, nothing changes and the message is
Success: nothing changed.
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_failed | The body is empty or not valid, sends code or kind, sends a field that the activity's kind does not have, carries a location that is not plausible or reaches more than 1 mile, redraws a boundary that is no longer active, or jobCode or equipmentCode names nothing in the company |
| 403 | insufficient_scope | The key does not have activity:write |
| 403 | forbidden | location is sent without geofences:write, or the key has no source system |
| 404 | not_found | No activity has this id within the key's companies, or location.geofenceId is not one of its boundaries |
| 409 | conflict | The activity belongs to another source system. Or expectedUpdatedAt does not match (the activity changed after you read it). Or location has no geofenceId and the activity has several boundaries or one that another owner holds. Or the boundary is locally managed or owned by another source system. |
| 500 | internal_error | The activity could not be updated |
POST /activities/import
Creates or updates up to 1,000 rows in one request. Use it for a first load or a nightly sync.
Scope: activity:write. Rows with a boundary also need geofences:write, or the whole
import gets 403.
How rows become activities
- One row per Phase Code. Rows with the same
codemake one activity. - The first row of a group gives the kind, name, address, division, time zone,
completeStatusandjobCode. A later row with a different name, address or division is a warning. A later row of another kind is an error. - Each group's Phase Codes replace the activity's list. A Job or Work Order group with no
phaseCodeleaves the list as it is. - Each group is saved on its own. One bad group does not stop the others.
- An existing activity is updated only when your source system owns it and it is the same kind.
- An activity of the same kind that another source system owns is never changed. If every
value that the group sends is equal to what Matrix TimeCard shows, the group counts as
unchanged. If a value is different, the row is an error that names the owner and the fields. A field that the group does not send is not compared. - Any other holder of the code is a row error.
- Boundaries: import adds a boundary only to an activity that has none. It never moves
an existing boundary. To move one, send
locationonPATCH /activities/{activityId}. A location that is not usable is a warning, and the activity is imported without it. - A group with more than 1,000 Phase Codes or more than 100 distinct locations is a row error.
- Send
"dryRun": truefirst. It checks every row, reports what would happen and saves nothing.
Request body
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
companyCode | string | No | Max 10 characters | The company. Required when the key covers more than one company. | |
dryRun | boolean | No | false | true checks every row and saves nothing | |
rows | array | Yes | 1 to 1,000 items | The rows | |
rows[].kind | string | Yes | Job, WorkOrder, MeetPoint | The kind | |
rows[].code | string | Yes | Max 50 characters | The activity's code | |
rows[].name | string | Yes | Max 100 characters | The name | |
rows[].divisionCode | string | No | Max 20 characters | The division | |
rows[].phaseCode | string | No. Required on a Meet Point row. | Max 50 characters | One Phase Code | |
rows[].phaseDescription | string | No | Max 200 characters | The Phase Code's description | |
rows[].address | string | No | Max 300 characters | The site address | |
rows[].latitude | number | No | The site point | ||
rows[].longitude | number | No | The site point | ||
rows[].radiusMeters | integer | No | 201 | 1 to 1,609 | The boundary radius in metres |
rows[].boundary | array | No | 3 or more points | A drawn boundary of { "lat", "lng" } points. Wins over latitude and longitude. | |
rows[].boundary[].lat | number | Latitude | |||
rows[].boundary[].lng | number | Longitude | |||
rows[].timeZone | string | No | Max 64 characters, IANA name | The time zone | |
rows[].completeStatus | string | No | Incomplete, Complete | Work Order only | |
rows[].jobCode | string | No | Max 50 characters | Work Order only | |
rows[].equipmentCode | string or null | No | Max 50 characters | Work Order only. Null clears it. | |
rows[].audienceDivisionCode | string or null | No | Max 20 characters | Meet Point only. The division side of one audience pair. Blank or null means any. | |
rows[].audiencePayClassCode | string or null | No | Max 30 characters | Meet Point only. The pay class side of one audience pair. |
Example request
curl -X POST "$TIMECARD_BASE_URL/activities/import" \
-H "X-API-Key: $TIMECARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"companyCode": "ACME",
"dryRun": true,
"rows": [
{
"kind": "Job", "code": "J-2026-110", "name": "Hwy 71 Overlay",
"divisionCode": "PAVING", "address": "Hwy 71 & FM 973, Austin, TX",
"latitude": 30.2033, "longitude": -97.6681, "radiusMeters": 400,
"timeZone": "America/Chicago",
"phaseCode": "01-100", "phaseDescription": "Mobilization"
},
{
"kind": "Job", "code": "J-2026-110", "name": "Hwy 71 Overlay",
"phaseCode": "04-400", "phaseDescription": "Asphalt overlay"
}
]
}'
Example response 200 OK
{
"status": 200,
"message": "Success: dry run complete. Nothing was written.",
"record": {
"dryRun": true,
"created": 1,
"updated": 0,
"unchanged": 0,
"phaseCodesAdded": 2,
"fencesCreated": 1,
"errors": [],
"warnings": []
}
}
Without dryRun, the message is Success: activity import complete.
Response fields
| Field | Type | Description |
|---|---|---|
record.dryRun | boolean | True when nothing was saved |
record.created | integer | Activities created (or that would be, on a dry run) |
record.updated | integer | Activities updated |
record.unchanged | integer | Activities that already held these values |
record.phaseCodesAdded | integer | Phase Codes added |
record.fencesCreated | integer | Boundaries added |
record.errors[].row | integer | The row's position in rows, starting at 1 |
record.errors[].message | string | Why the row's activity was refused |
record.warnings[].row | integer | The row's position in rows, starting at 1 |
record.warnings[].message | string | What was doubted or skipped |
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_failed | The body is not JSON, rows is empty or has more than 1,000 items, or companyCode is missing when the key covers several companies. A bad row is reported in errors, not here. |
| 403 | insufficient_scope | The key does not have activity:write |
| 403 | forbidden | The key names another company, rows carry a boundary without geofences:write, or the key has no source system |
| 404 | not_found | companyCode names no active company that the key can reach |
| 500 | internal_error | The import could not run |