Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion docs/api/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ sidebar_position: 2

Resgrid as of the v4 version of the API uses the JWT (JSON Web Token) <https://jwt.io/> standard with OpenID Connect. You need to auth to the Resgrid API via a specific endpoint before you can call operations against the API.

A system-to-system integration that should not sign in as a person can use a [department API key](#department-api-keys) instead.

## Connect Operation

To Authenticate with the Resgrid API you need to submit a POST request to the the `v4/connect/token` endpoint. Once this is done you will have the data needed to make subsequent calls the the other functions on the Resgrid API.
Expand Down Expand Up @@ -95,4 +97,56 @@ Example Response:
"PreviousPageUrl":null,
"NextPageUrl":null
}
```
```


## Department API keys

Use a **department API key** when another system, rather than a person, calls Resgrid: a scheduling or case-management system that feeds in follow-up calls, a records system that reads calls, a CAD bridge. The key belongs to the department, not to a member, so there is no username or password to store in that system and nothing breaks when someone leaves.

A department admin creates keys under **Security → API Keys** in the web app ([Security & Permissions](../web-app/security-permissions#api-keys)). Each key:

- can only call the endpoints of the **scopes** you choose (below), and nothing else;
- has an **expiry date** (30 days to 2 years) after which it stops working;
- can be **revoked** at any time, which takes effect at once;
- can optionally be limited to **source addresses** (IP addresses or CIDR ranges);
- is shown **once**, when it is created. Resgrid stores only a keyed hash of it, so a lost key cannot be recovered: revoke it and create another.

Send the key in the `X-Resgrid-ApiKey` header. There is no token exchange and no refresh step. Never put a key in a URL or query string, and do not send a bearer token with it.

```bash
curl -X POST "https://api.resgrid.com/api/v4/Calls/SaveCall" \
-H "X-Resgrid-ApiKey: rgk_XXXXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "Name": "Follow-up visit", "Nature": "Post-discharge check", "Priority": 1, "Type": "Follow-up", "IsPending": true, "ExternalId": "EHR-55120" }'
```

### Scopes

| Scope | Endpoints (`api/v4/...`) |
|---|---|
| `calls.read` | `Calls/GetActiveCalls`, `Calls/GetCall`, `Calls/GetCalls`, `Calls/GetPendingCalls`, `Calls/GetAllPendingScheduledCalls`, `Calls/GetNewCallFieldPolicy` |
| `calls.create` | `Calls/SaveCall`, including pending (`IsPending`) and scheduled (`DispatchOn` / `DispatchOnUtc`) calls |
| `calls.update` | `Calls/EditCall`, `Calls/DispatchCallNow`, `Calls/UpdateScheduledDispatchTime` |
| `calls.close` | `Calls/CloseCall` |
| `reference.read` | `CallTypes/GetAllCallTypes`, `CallPriorities/GetAllCallPriorites`, `Dispatch/GetCallTemplates`, `Groups/GetAllGroups`, `Dispatch/GetRolesForCallGrid` (what you need to fill in a call and its dispatch list) |
| `units.read` | `Units/GetAllUnits`, `UnitStatus/GetAllUnitStatuses` |

Give a key only the scopes it needs. A system that only feeds in pending calls needs `calls.create` (and `reference.read` if it looks up types, priorities, groups or roles). No other endpoint accepts a key, whatever its scopes: deleting calls, personnel, messages and settings are always out of reach.

### What a key acts as

A request made with a key acts for the key's department. Department-wide checks run as the department's managing user, narrowed to the key's scopes, so a call created with a key shows the managing user as the reporting user. Use `ExternalId` (or `ReferenceId`) to carry your own system's id. Departments using [Advanced Data Protection](../web-app/data-protection) receive the protected fields through the broker's encrypt-only lane, the same as other unattended integrations; reads return them redacted.

### Errors

| Response | Meaning |
|---|---|
| `401` | The key is missing, unknown, expired, revoked or used from an address it is not allowed from. Also returned by every endpoint a key cannot call. |
| `403` | The key is valid but does not have the scope this endpoint needs, or the request also carries a bearer token. |

After repeated invalid keys from one address, further attempts from that address are refused for a few minutes.

### Rotating a key

Create the new key, switch the other system to it, check its **Last used** column in **Security → API Keys**, then revoke the old one. Every create and revoke is written to the [audit log](../web-app/security-permissions#audit-logs).
40 changes: 38 additions & 2 deletions docs/api/information.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,46 @@ The Resgrid API Exposes our Swagger documentation to showcase every call and ope

| Area | Description |
|------|-------------|
| **Authentication** | JWT/OpenID Connect token management |
| **Authentication** | JWT/OpenID Connect token management, and [department API keys](authentication#department-api-keys) for system integrations |
| **Statuses** | Personnel and unit status operations |
| **Calls** | Dispatch call management |
| **Calls** | Dispatch call management, including [pending and scheduled calls](#pending-and-scheduled-calls) |
| **Calendar** | Calendar events, types, and RSVP |
| **Calendar Export** | iCal export, department feed subscriptions, and sync token management (see [Calendar Export API](calendar-export)) |
| **Contact Verification** | Email and phone verification |
| **Workflows** | Automated workflow management |

## Pending and scheduled calls

Another system (case management, scheduling, a referral line) can hand work to your dispatchers without paging anyone: create the call as **pending**. It is saved and numbered, nobody is notified, and it stays out of the active call lists and the field apps until a dispatcher sends it from **Pending Calls** in the web app or the Dispatch app. See [Pending and scheduled calls](../web-app/dispatch-calls#pending-and-scheduled-calls).

An integration should use a [department API key](authentication#department-api-keys) with the `calls.create` scope rather than a member's login:

```http
POST /api/v4/Calls/SaveCall
X-Resgrid-ApiKey: rgk_XXXXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/json

{
"Name": "Follow-up: post-discharge wellness check",
"Nature": "Clinic requests an in-person check within 24 hours.",
"Priority": 1,
"Type": "Follow-up",
"Address": "550 S Vermont Ave, Los Angeles, CA 90020",
"ContactName": "Client J.R.",
"ExternalId": "EHR-55120",
"IsPending": true
}
```

| Endpoint | Purpose |
|---|---|
| `POST Calls/SaveCall` with `"IsPending": true` | Create a pending call. `DispatchList` is optional and kept as the proposed recipients (empty = none, `"0"` = everyone); `DispatchOn` is ignored; the department's dispatch-list and dispatch-time requirements do not apply. Use `ExternalId` for your own case or ticket number. |
| `GET Calls/GetPendingCalls` | Pending calls, oldest first. A call's `State` is `8` while pending. |
| `PUT Calls/DispatchCallNow` | Body `{ "CallId": "123", "DispatchList": "U:5\|R:7" }`. Sends a pending call, or a scheduled call that has not gone out, right now. Leave `DispatchList` out to use the recipients already on the call. Returns 400 with a message when the call is not waiting or has nobody to send to. |
| `PUT Calls/EditCall` | Edits a pending call without notifying anyone. A future `DispatchOn` turns it into a scheduled call. |
| `PUT Calls/CloseCall` | Body `{ "Id": "123", "Type": 1, "Notes": "...", "SendNotification": true }`. Closes a call (close states 1–7). With `SendNotification`, everyone on a call that went out is told it closed: the personnel, groups and roles it was dispatched to, its units, and the incident command team. A pending call, or a scheduled call that never went out, notifies nobody. Returns 400 while the call has an active incident command: close the command first (the Incident Command app can close the call in the same step). |
| `GET Calls/GetAllPendingScheduledCalls`, `PUT Calls/UpdateScheduledDispatchTime` | Scheduled calls that have not been sent yet, and moving their dispatch time. |

A **scheduled** call is created the same way without `IsPending`, with a future dispatch time: `DispatchOn` in the department's local time, or `DispatchOnUtc` in UTC (for example `"2026-10-07T14:30:00Z"`; it wins when both are sent). It goes out by itself within five minutes of that time, or earlier with `DispatchCallNow`.

`Priority` is the id of one of your department's call priorities (`GET CallPriorities/GetAllCallPriorites`) and `Type` the name of a call type. Dispatch lists use `P:` personnel, `G:` groups, `R:` roles and `U:` units, separated by `|`.
148 changes: 148 additions & 0 deletions docs/api/map-icons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
---
sidebar_position: 9
---

# Map Icons API

Map markers carry the icon a client should draw, and the map icon legend endpoint returns every icon a department's map can show. Both are part of the v4 API and are built from the same department data, so a client that draws its markers and its legend from them always matches the web map. For what the icons mean and how departments set them up, see [Icons by status and priority](../web-app/mapping#icons-by-status-and-priority), [Map icon legend](../web-app/mapping#map-icon-legend) and [Custom map icons](../web-app/mapping#custom-map-icons).

## Endpoints Overview

| Endpoint | Method | Auth | Description |
|----------|--------|------|-------------|
| `/api/v4/Mapping/GetMapDataAndMarkers` | GET | Bearer token, `Call_View` | The department map: markers for calls, units, stations, personnel, POIs and hydrants |
| `/api/v4/Mapping/GetUnitMapData` | GET | Bearer token, `Call_View` | One unit and the members seated in its roles |
| `/api/v4/Mapping/GetMapIconLegend` | GET | Bearer token, `Call_View` | Every icon the department's map can show, for an in-app legend |
| `/api/v4/TypeIcons/{key}` | GET | Anonymous | A department's uploaded icon (128 × 128 PNG); `?s={style}` adds a badge in the style's color |
| `/api/v4/TypeIcons/Pins/{base}-{style}` | GET | Anonymous | A built-in pin recolored to a style (32 × 37 PNG, tip at the bottom center) |

Icon and pin URLs carry `v=` (the palette version) and are served with `Cache-Control: public, max-age=31536000, immutable`. A changed upload gets a new key and a changed palette a new `v`, so a cached image is never stale.

## Marker icon fields

Call (`Type` 0), unit (1) and personnel (3) markers carry four icon fields:

| Field | Description |
|-------|-------------|
| `IconUrl` | The department's uploaded icon: the one uploaded for the current priority or status, else the type's or role's own icon with a badge in the color of `IconStyle`. Null when there is none |
| `PinIconUrl` | The built-in pin the type picked (or the default call, unit or person pin), recolored to `IconStyle` |
| `ImagePath` | The plain bundled icon name (`fire`, `ambulance`, `Call`, `Engine_Responding`, `Person_RespondingCall`), for clients without styled pins |
| `IconStyle` | The style of the priority or status (see [Styles](#styles)) |

Draw `IconUrl` if set, else `PinIconUrl`, else the bundled `ImagePath` image. If a remote image fails to load, fall back to the next one. Stations, POIs and hydrants have no `PinIconUrl` or `IconStyle`; POIs and POI layers carry their own `IconUrl` when the POI type has an uploaded icon.

## Styles

A style is the color group of a status or priority meaning. Keys are stable wire values.

| Key | Color | Covers |
|-----|-------|--------|
| `available` | `#2E9E44` | Available, Cleared, On Patrol, Completed, In Quarters |
| `dispatched` | `#B7791F` | Dispatched |
| `responding` | `#D93A1E` | Responding, En Route |
| `onscene` | `#1D5FD1` | On Scene, Made Contact, Investigating, At Patient, Searching |
| `transporting` | `#7A3EBE` | Transporting, Delivering, Loading, At Hospital |
| `returning` | `#0C8C99` | Returning |
| `staging` | `#8A6A3A` | Staging, Standby |
| `delayed` | `#607D8B` | On Break |
| `unavailable` | `#3D3D3D` | Unavailable, Maintenance, Not Responding |
| `low` / `medium` / `high` / `emergency` | `#2E8B3E` / `#B59A00` / `#E07800` / `#C8102E` | Call priorities by meaning |
| `unknown` | `#8A8A8A` | A status or priority with no meaning whose name suggests none, or a unit or member with no status |

A member *On Unit* takes the style of their unit's latest status.

## Get Map Icon Legend

```
GET /api/v4/Mapping/GetMapIconLegend
```

Returns the department's legend in the standard v4 envelope. Everything in it comes from the department's own setup: call types, priorities, unit types and their status sets, personnel statuses, roles, POI types, the built-in icon each type picked and every uploaded icon. Fetch it when the legend is opened rather than caching it, so a change shows on the next open.

### Response data

| Field | Description |
|-------|-------------|
| `StatusStyles` | The nine status styles in legend order, then `unknown`. Each has `Key`, `Color`, `Meanings` (status meaning values), `UnitStatuses` and `PersonnelStatuses` (the department's own status names in that style), `UnitPinIconUrl` and `PersonPinIconUrl` |
| `PriorityStyles` | `low`, `medium`, `high`, `emergency`, then `unknown`. Each has `Key`, `Color`, `Priorities` (the department's own priority names) and `CallPinIconUrl` |
| `Calls` | Calls with no type first (`Id` null), then each call type by name; one state per active priority |
| `Units` | Units with no type first (`Id` null), then each unit type by name; one state per status of the type's status set (`StatusSetName`, null for the built-in unit statuses) |
| `Personnel` | Members with no role icon first (`Id` null), then each role with an uploaded icon, in role order; one state per personnel status |
| `PoiTypes` | Each POI type: `PoiTypeId`, `Name`, `Color`, `PoiImage`, `ImagePath`, `Marker`, `IconUrl` |

A row has `Id`, `Name`, `StatusSetName` (units), its own icon (`IconUrl`, `ImagePath`) and `States`. The `Name` of an `Id`-null row is a generic label in the server's language; clients should show their own localized label. A state has:

| Field | Description |
|-------|-------------|
| `Id` | The stored priority id or status id |
| `Name` | The department's name for it |
| `Color` | The priority's or status's own hex color, or null |
| `IconStyle` | Its style; `unknown` when it has no meaning |
| `IconUrl`, `PinIconUrl`, `ImagePath` | The icon a marker of the row shows in it, as on [markers](#marker-icon-fields) |
| `IsVariant` | True when `IconUrl` was uploaded for this very priority or status |
| `FollowsUnitStatus` | True for the built-in *On Unit* personnel status: on the map the member takes their unit's style, and the gray pin given here applies only when there is no unit status to follow |

### Example

```json
{
"Data": {
"StatusStyles": [
{
"Key": "available",
"Color": "#2E9E44",
"Meanings": [0, 7, 19, 22, 23],
"UnitStatuses": ["Available", "In Quarters"],
"PersonnelStatuses": ["Standing By"],
"Priorities": [],
"UnitPinIconUrl": "https://api.resgrid.com/api/v4/TypeIcons/Pins/engine-available?v=1",
"PersonPinIconUrl": "https://api.resgrid.com/api/v4/TypeIcons/Pins/person-available?v=1",
"CallPinIconUrl": null
}
],
"PriorityStyles": [
{
"Key": "emergency",
"Color": "#C8102E",
"Meanings": [],
"UnitStatuses": [],
"PersonnelStatuses": [],
"Priorities": ["P1 Life threat"],
"UnitPinIconUrl": null,
"PersonPinIconUrl": null,
"CallPinIconUrl": "https://api.resgrid.com/api/v4/TypeIcons/Pins/call-emergency?v=1"
}
],
"Calls": [
{
"Id": 11,
"Name": "Structure Fire",
"StatusSetName": null,
"IconUrl": null,
"PinIconUrl": null,
"ImagePath": "fire",
"States": [
{
"Id": 901,
"Name": "P1 Life threat",
"Color": "#ff0000",
"IconStyle": "emergency",
"IconUrl": null,
"PinIconUrl": "https://api.resgrid.com/api/v4/TypeIcons/Pins/fire-emergency?v=1",
"ImagePath": "fire",
"IsVariant": false,
"FollowsUnitStatus": false
}
]
}
],
"Units": [],
"Personnel": [],
"PoiTypes": []
},
"PageSize": 1,
"Status": "success"
}
```

The Responder, Unit and IC apps show this legend as a sheet over their maps; the web app shows it at **Mapping → Map Icon Legend**. Both are built by `MapIconLegendBuilder` from the department's `MapIconResolver`.
Loading
Loading