pulpo

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 11 Imported by: 0

README

pulpo

Go Reference

A flexible Go client library for an emergency-dispatch HTTP API.

pulpo gives you typed access to the endpoints that have been modeled, a raw json.RawMessage result for the ones that haven't, and a low-level escape hatch for anything else. Configuration uses the functional-options pattern; the base URL and API key are supplied by you at construction time — nothing is hardcoded.

The full API reference is on pkg.go.dev.

Install

go get github.com/michaelpeterswa/pulpo

Quickstart

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/michaelpeterswa/pulpo"
)

func main() {
	client, err := pulpo.NewClient(
		pulpo.WithBaseURL("https://api.example.invalid/v1"), // you provide this
		pulpo.WithAPIKey("your-api-key"),                    // required
		pulpo.WithBasicAuth("user", "pass"),                 // optional
	)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.Agencies.Search(context.Background(), "seattle", nil)
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range resp.SearchAgencies {
		fmt.Printf("%s (%s)\n", a.Display1, a.AgencyID)
	}
}

Configuration

NewClient takes functional options. WithBaseURL and WithAPIKey are required; the rest are optional.

Option Required Purpose
WithBaseURL(string) yes Full base URL including scheme, host, and version segment (e.g. .../v1 or .../v2).
WithAPIKey(string) yes Sent as the apikey query parameter on every request.
WithBasicAuth(user, pass) no HTTP Basic auth sent on every request.
WithHTTPClient(*http.Client) no Use your own HTTP client (timeouts, transport, etc.).
WithUserAgent(string) no Override the User-Agent header.

The API key is added to every request automatically, and basic-auth is applied when configured — you never have to thread them through individual calls.

Services

Endpoints are grouped into services on the client:

Service Highlights
client.Agencies Search, ListAll, Followed, Get, GetByAgencyID, Selected, Shape
client.Incidents List, Get
client.CPR Active, Respond
client.AED NearestForIncident, LayerData
client.MapLayers Available, Stations, Data (raw, freeform layer query)
client.Units Legend, Groups, GetSubscriptions, UpdateSubscriptions
client.Settings Get, Update, GetApp, UpdateApp, ApplicationStatus
client.Location Get, Update, RegionStrings
client.Surveys Get, Clear
client.Responder UpdateProfileImage, RegisterVerified
client.Notifications SendTestFCM

Typed vs. raw responses

Endpoints whose response shapes have been modeled from live traffic return typed structs:

  • Agencies.Search / ListAll / Followed*SearchAgenciesResponse
  • Agencies.Get*Agency, Agencies.GetByAgencyID*AgenciesResponse
  • Agencies.Shape*Geometry
  • Incidents.List*IncidentsResponse, Incidents.Get*Incident
  • CPR.Active*CPRResponse
  • AED.NearestForIncident / LayerData*AEDResponse
  • MapLayers.Available*AvailableLayersResponse, MapLayers.Stations*StationsResponse
  • Units.Legend*UnitLegendResponse, Units.Groups*UnitGroupsResponse, Units.GetSubscriptions*UnitGroupSubscriptions
  • Location.RegionStrings*RegionStringsResponse

Endpoints that still need a real device/session to observe (device settings, stored location, followed-agency map view), the freeform map-layer query, and all POST bodies return encoding/json.RawMessage so you can decode them however you like:

raw, err := client.Settings.Get(ctx, deviceID)
if err != nil {
	log.Fatal(err)
}
var settings map[string]any
_ = json.Unmarshal(raw, &settings)
Escape hatch

For any endpoint the typed methods don't cover, call client.Do directly:

var out json.RawMessage
err := client.Do(ctx, "GET", "some/endpoint", url.Values{"key": {"value"}}, nil, &out)

It applies the same auth, base-URL resolution, and error handling as the typed methods.

A note on data shapes

The upstream API usually returns numeric-looking values — identifiers, coordinates, boolean-like flags — as JSON strings. Typed models keep those fields as string to match the wire format. (A few endpoints break the pattern: UnitGroup.GroupID and SortOrder come back as real JSON numbers and are typed as int.) Convenience accessors are provided where a parsed value is commonly needed:

lat, lng, err := incident.LatLng() // also on AED and Station
Unmodeled agency fields

Agency records vary from agency to agency. Any field the API returns that isn't represented by a typed field is preserved in Agency.Extra (map[string]json.RawMessage) rather than dropped, so nothing is lost and you can still reach newly-added fields:

a, err := client.Agencies.Get(ctx, "371", nil)
if err != nil {
	log.Fatal(err)
}
fmt.Println(a.AgencyName)          // typed field
if raw, ok := a.Extra["some_new_field"]; ok {
	// decode raw (json.RawMessage) however you like
	_ = raw
}

Extra is nil when the response contains no unmodeled fields.

Errors

Non-2xx responses are returned as *pulpo.APIError, carrying the status code and raw body:

if apiErr, ok := pulpo.AsAPIError(err); ok {
	log.Printf("status %d: %s", apiErr.StatusCode, apiErr.Body)
}

Error bodies are often the API's status envelope ({"StatusCode":"400","StatusDescription":"..."}), which you can decode with a helper:

if apiErr, ok := pulpo.AsAPIError(err); ok {
	if sr, ok := apiErr.StatusResponse(); ok {
		log.Printf("%s: %s", sr.StatusCode, sr.StatusDescription)
	}
}

License

See LICENSE.

Documentation

Overview

Package pulpo is a flexible Go client for an emergency-dispatch HTTP API.

The client is constructed with the functional-options pattern. The base URL and API key are required; basic-auth credentials, a custom *http.Client, and a user agent are optional:

client, err := pulpo.NewClient(
	pulpo.WithBaseURL("https://example.invalid/v1"),
	pulpo.WithAPIKey("your-api-key"),
	pulpo.WithBasicAuth("user", "pass"),
)
if err != nil {
	// handle err
}

Endpoints are grouped into services that hang off the Client (client.Agencies, client.Incidents, ...). Responses that have been modeled are returned as typed structs; everything else is returned as encoding/json.RawMessage. For any request the typed helpers do not cover, use the low-level Client.Do escape hatch.

Note on data shapes: the upstream API frequently returns numeric-looking values (identifiers, coordinates, boolean-like flags) as JSON strings. Typed models keep those fields as strings to match the wire format; convenience accessors are provided where a parsed value is commonly needed.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AED

type AED struct {
	Name              string `json:"Name"`
	Description       string `json:"Description"`
	LatitudeLongitude string `json:"LatitudeLongitude"`
	Private           string `json:"Private"`
	AEDImage          string `json:"AEDImage,omitempty"`
}

AED is a defibrillator location. Private is a boolean-like string ("0"/"1"). AEDImage is only present for some records.

func (AED) LatLng

func (a AED) LatLng() (lat, lng float64, err error)

LatLng parses the AED's "lat,lng" LatitudeLongitude field.

type AEDResponse

type AEDResponse struct {
	AEDs []AED `json:"aeds"`
}

AEDResponse is the envelope returned by the AED endpoints.

type AEDService

type AEDService struct {
	// contains filtered or unexported fields
}

AEDService covers defibrillator (AED) location endpoints.

func (*AEDService) LayerData

func (s *AEDService) LayerData(ctx context.Context, viewport, vrid string) (*AEDResponse, error)

LayerData returns AED map-layer data within a viewport bounding box ("lat1,lng1,lat2,lng2").

func (*AEDService) NearestForIncident

func (s *AEDService) NearestForIncident(ctx context.Context, incidentID, vrid string) (*AEDResponse, error)

NearestForIncident returns the AEDs nearest to a given incident.

type APIError

type APIError struct {
	// StatusCode is the HTTP status code of the response (e.g. 404).
	StatusCode int
	// Status is the HTTP status line of the response (e.g. "404 Not Found").
	Status string
	// Body is the raw response body, if any was returned.
	Body []byte
}

APIError is returned when the API responds with a non-2xx status code. It carries the HTTP status and the raw response body so callers can inspect the upstream error payload.

func AsAPIError

func AsAPIError(err error) (*APIError, bool)

AsAPIError reports whether err is (or wraps) an *APIError and, if so, returns it. It is a thin convenience wrapper around errors.As.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

func (*APIError) StatusResponse

func (e *APIError) StatusResponse() (StatusResponse, bool)

StatusResponse attempts to decode the error body as the API's status envelope ({"StatusCode":..., "StatusDescription":...}). It reports false if the body is empty or not in that shape.

type AgenciesResponse

type AgenciesResponse struct {
	Agencies []Agency `json:"agencies"`
}

AgenciesResponse is the envelope returned by the by-agency-code lookup.

type AgenciesService

type AgenciesService struct {
	// contains filtered or unexported fields
}

AgenciesService covers agency search, lookup, and boundary endpoints.

func (*AgenciesService) Followed

Followed returns the agencies a given device follows.

func (*AgenciesService) Get

func (s *AgenciesService) Get(ctx context.Context, id string, opts *AgencyOptions) (*Agency, error)

Get returns the full detail for a single agency. Note that id is the numeric agency id (the "id" field of a search result, e.g. "371"), not the agency code ("17M15"). Pass WithBaseURL-appropriate options via opts.

func (*AgenciesService) GetByAgencyID

func (s *AgenciesService) GetByAgencyID(ctx context.Context, agencyIDs string, opts *AgencyOptions) (*AgenciesResponse, error)

GetByAgencyID looks up one or more agencies by comma-separated agency codes (for example "17M15").

func (*AgenciesService) ListAll

ListAll returns every agency.

func (*AgenciesService) Search

Search returns agencies matching a free-text token (city or agency name).

func (*AgenciesService) Selected

func (s *AgenciesService) Selected(ctx context.Context, deviceID string, opts *AgencyOptions) (json.RawMessage, error)

Selected returns the agencies selected/followed by a device (map view). The response schema is not yet modeled, so raw JSON is returned.

func (*AgenciesService) Shape

func (s *AgenciesService) Shape(ctx context.Context, ogrFID string, opts *AgencyOptions) (*Geometry, error)

Shape returns an agency boundary as a GeoJSON geometry, by its internal OGR feature id (the "ogr_fid" field of an Agency).

type Agency

type Agency struct {
	ID                       string        `json:"id"`
	AgencyID                 string        `json:"agencyid"`
	AgencyName               string        `json:"agencyname"`
	ShortAgencyName          string        `json:"short_agencyname"`
	AgencyInitials           string        `json:"agency_initials"`
	AgencyType               string        `json:"agencytype"`
	AgencyDescription        string        `json:"agency_description"`
	AgencyWebsite            string        `json:"agency_website"`
	AgencyImage              string        `json:"agencyimage"`
	AgencyLatitude           string        `json:"agency_latitude"`
	AgencyLongitude          string        `json:"agency_longitude"`
	Boundary                 string        `json:"boundary"`
	BoundaryCentroid         string        `json:"boundary_centroid"`
	CitiesServed             []CityServed  `json:"cities_served"`
	City                     string        `json:"city"`
	State                    string        `json:"state"`
	Country                  string        `json:"country"`
	Timezone                 string        `json:"timezone"`
	PSAP                     string        `json:"psap"`
	OGRFID                   string        `json:"ogr_fid"`
	Status                   string        `json:"status"`
	CPROnly                  string        `json:"cpr_only"`
	TestAgency               string        `json:"testagency"`
	HasStations              string        `json:"has_stations"`
	HasUnitGroups            string        `json:"has_unit_groups"`
	HasUnitLegend            string        `json:"has_unit_legend"`
	PublicEmail              string        `json:"public_email"`
	FacebookName             string        `json:"facebookname"`
	InstagramName            string        `json:"instagramname"`
	LinkedInName             string        `json:"linkedinname"`
	TwitterName              string        `json:"twittername"`
	YouTubeURL               string        `json:"youtubeURL"`
	SponsorImage             string        `json:"sponsorimage"`
	LightContextAgencyImage  string        `json:"lightcontext_agencyimage"`
	DarkContextAgencyImage   string        `json:"darkcontext_agencyimage"`
	LightContextSponsorImage string        `json:"lightcontext_sponsorimage"`
	DarkContextSponsorImage  string        `json:"darkcontext_sponsorimage"`
	LivestreamURL            string        `json:"livestreamurl"`
	LiveRadio                []RadioStream `json:"live_radio"`

	// Extra holds any fields returned by the API that are not represented by a
	// typed field above (they vary by agency). It is nil when there are none.
	Extra map[string]json.RawMessage `json:"-"`
}

Agency is the full detail record for an agency. Numeric-looking and boolean-like fields (coordinates, has_stations, cpr_only, testagency, ...) are returned by the API as strings. Fields are populated on a best-effort basis; expect some to be empty depending on the agency and endpoint.

func (*Agency) UnmarshalJSON

func (a *Agency) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes an Agency, collecting any keys without a typed field into Extra.

type AgencyOptions

type AgencyOptions struct {
	// GeoJSON includes GeoJSON boundary geometry in the response when true.
	GeoJSON bool
	// VRID is the verified-responder id; leave empty when not applicable.
	VRID string
}

AgencyOptions holds optional parameters for agency lookup and boundary endpoints.

type AgencySearchOptions

type AgencySearchOptions struct {
	// Sandbox selects the sandbox review filter (reviewed=1) instead of the
	// production approval filter (approved=1).
	Sandbox bool
}

AgencySearchOptions holds optional parameters for the agency search/list endpoints.

type AgencySearchResult

type AgencySearchResult struct {
	Type     string  `json:"Type"`
	Display1 string  `json:"Display1"`
	Display2 string  `json:"Display2"`
	ID       string  `json:"id"`
	Lat      float64 `json:"lat"`
	Lng      float64 `json:"lng"`
	AgencyID string  `json:"agencyid"`
}

AgencySearchResult is a single entry returned by the agency search/list endpoints. Numeric-looking fields are returned by the API as strings.

type AvailableLayer

type AvailableLayer struct {
	Type          string    `json:"Type"`
	LocalizedName string    `json:"LocalizedName"`
	Image         string    `json:"Image"`
	MinZoomLevel  string    `json:"MinZoomLevel"`
	PinStyle      string    `json:"PinStyle"`
	ZPriority     string    `json:"Z-Priority"`
	PinIcons      []PinIcon `json:"PinIcons"`
}

AvailableLayer describes one selectable map layer. Numeric-looking fields (MinZoomLevel) are returned as strings.

type AvailableLayersResponse

type AvailableLayersResponse struct {
	AvailableLayers []AvailableLayer `json:"AvailableLayers"`
}

AvailableLayersResponse is the envelope returned by the available-layers endpoint.

type CPRResponse

type CPRResponse struct {
	Incidents []json.RawMessage `json:"incidents"`
}

CPRResponse is the envelope returned by the active-CPR-events endpoint. Incidents is null when no events are active. The per-event schema is not yet modeled, so events are returned as raw JSON.

type CPRService

type CPRService struct {
	// contains filtered or unexported fields
}

CPRService covers CPR-needed events and responses.

func (*CPRService) Active

func (s *CPRService) Active(ctx context.Context, deviceID string) (*CPRResponse, error)

Active returns the active CPR-needed events near a device.

func (*CPRService) Respond

func (s *CPRService) Respond(ctx context.Context, body any) (json.RawMessage, error)

Respond submits a response to a CPR alert. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

type CityServed

type CityServed struct {
	City      string `json:"City"`
	StateProv string `json:"StateProv"`
	Country   string `json:"Country"`
}

CityServed is a single entry in an agency's cities_served list.

type Client

type Client struct {

	// Services group the endpoints by area. They are wired up by NewClient.
	Agencies      *AgenciesService
	Incidents     *IncidentsService
	CPR           *CPRService
	AED           *AEDService
	MapLayers     *MapLayersService
	Units         *UnitsService
	Settings      *SettingsService
	Location      *LocationService
	Surveys       *SurveysService
	Responder     *ResponderService
	Notifications *NotificationsService
	// contains filtered or unexported fields
}

Client is a client for the emergency-dispatch HTTP API. Construct one with NewClient. A Client is safe for concurrent use by multiple goroutines.

Example

ExampleClient shows constructing a client and calling a typed endpoint. A mock server stands in for the real API so the example is self-contained.

package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/michaelpeterswa/pulpo"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte(`{"searchagencies":[{"agencyid":"17M15","Display1":"Seattle FD [WA]"}]}`))
	}))
	defer srv.Close()

	client, err := pulpo.NewClient(
		pulpo.WithBaseURL(srv.URL+"/v1"), // caller supplies the base URL
		pulpo.WithAPIKey("your-api-key"),
		pulpo.WithBasicAuth("user", "pass"),
	)
	if err != nil {
		panic(err)
	}

	resp, err := client.Agencies.Search(context.Background(), "seattle", nil)
	if err != nil {
		panic(err)
	}
	for _, a := range resp.SearchAgencies {
		fmt.Printf("%s: %s\n", a.AgencyID, a.Display1)
	}
}
Output:
17M15: Seattle FD [WA]

func NewClient

func NewClient(opts ...Option) (*Client, error)

NewClient constructs a Client from the given options. WithBaseURL and WithAPIKey are required; NewClient returns an error if either is missing or if any option fails to apply.

func (*Client) BaseURL

func (c *Client) BaseURL() *url.URL

BaseURL returns a copy of the configured base URL.

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, query url.Values, body, out any) error

Do is a low-level escape hatch for calling any endpoint the typed service methods do not cover. It applies the same auth, base-URL resolution, and error handling as the typed methods. body is JSON-encoded when non-nil, and out receives the decoded 2xx response (use *json.RawMessage for raw JSON, or nil to discard).

Example

ExampleClient_Do shows the low-level escape hatch for endpoints without a typed helper.

package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/michaelpeterswa/pulpo"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte(`{"status":"ok"}`))
	}))
	defer srv.Close()

	client, _ := pulpo.NewClient(
		pulpo.WithBaseURL(srv.URL+"/v1"),
		pulpo.WithAPIKey("your-api-key"),
	)

	var raw map[string]string
	if err := client.Do(context.Background(), "GET", "some/endpoint", nil, nil, &raw); err != nil {
		panic(err)
	}
	fmt.Println(raw["status"])
}
Output:
ok

type Geometry

type Geometry struct {
	Type        string          `json:"type"`
	Coordinates json.RawMessage `json:"coordinates"`
}

Geometry is a GeoJSON geometry as returned by boundary endpoints. Coordinates are left raw because their nesting depth varies by geometry type (Polygon vs. MultiPolygon, etc.).

type Incident

type Incident struct {
	ID                             string `json:"ID"`
	AgencyID                       string `json:"AgencyID"`
	Latitude                       string `json:"Latitude"`
	Longitude                      string `json:"Longitude"`
	PublicLocation                 string `json:"PublicLocation"`
	CallType                       string `json:"PulsePointIncidentCallType"`
	CallReceivedDateTime           string `json:"CallReceivedDateTime"`
	IsShareable                    string `json:"IsShareable"`
	FullDisplayAddress             string `json:"FullDisplayAddress"`
	MedicalEmergencyDisplayAddress string `json:"MedicalEmergencyDisplayAddress"`
	AddressTruncated               string `json:"AddressTruncated"`
	Unit                           []Unit `json:"Unit"`
}

Incident is a single dispatch incident. Numeric-looking and boolean-like fields (ID, Latitude, Longitude, PublicLocation, IsShareable, AddressTruncated) are returned by the API as JSON strings; they are kept as strings here to match the wire format.

func (Incident) LatLng

func (i Incident) LatLng() (lat, lng float64, err error)

LatLng parses the incident's Latitude and Longitude string fields into float64 values.

type IncidentBuckets

type IncidentBuckets struct {
	Alerts []Incident `json:"alerts"`
	Active []Incident `json:"active"`
	Recent []Incident `json:"recent"`
}

IncidentBuckets groups incidents by state.

type IncidentGetOptions

type IncidentGetOptions struct {
	// AgencyID scopes the lookup to an agency; leave empty when not needed.
	AgencyID string
	// VRID is the verified-responder id; leave empty when not applicable.
	VRID string
}

IncidentGetOptions holds optional parameters for single-incident detail.

type IncidentListOptions

type IncidentListOptions struct {
	// Both returns both active and recent incidents when true.
	Both bool
	// VRID is the verified-responder id; leave empty when not applicable.
	VRID string
}

IncidentListOptions holds optional parameters for the incident feed.

type IncidentsResponse

type IncidentsResponse struct {
	Incidents IncidentBuckets `json:"incidents"`
}

IncidentsResponse is the envelope returned by the incident feed endpoint.

type IncidentsService

type IncidentsService struct {
	// contains filtered or unexported fields
}

IncidentsService covers the live-dispatch incident feed.

func (*IncidentsService) Get

Get returns detail for a single incident. The response is a single Incident object with the same shape as the feed entries.

func (*IncidentsService) List

List returns the active and recent incidents for an agency.

type LocationService

type LocationService struct {
	// contains filtered or unexported fields
}

LocationService covers device location and region-string endpoints.

func (*LocationService) Get

func (s *LocationService) Get(ctx context.Context, deviceID string) (json.RawMessage, error)

Get returns the last known location stored for a device. The response schema is not yet modeled, so raw JSON is returned.

func (*LocationService) RegionStrings

func (s *LocationService) RegionStrings(ctx context.Context, lat, lng float64) (*RegionStringsResponse, error)

RegionStrings returns human-readable region strings for a latitude/longitude.

func (*LocationService) Update

Update pushes a device location update. The response schema is not yet modeled, so raw JSON is returned.

type LocationUpdate

type LocationUpdate struct {
	DeviceID  string  `json:"deviceid"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
}

LocationUpdate is the request body for pushing a device location update.

type MapLayerOptions

type MapLayerOptions struct {
	// Viewport is a bounding box "lat1,lng1,lat2,lng2".
	Viewport string
	// AgencyID scopes the query to an agency.
	AgencyID string
	// VRID is the verified-responder id.
	VRID string
}

MapLayerOptions holds optional parameters for map-layer data queries.

type MapLayersService

type MapLayersService struct {
	// contains filtered or unexported fields
}

MapLayersService covers map-layer discovery and data endpoints.

func (*MapLayersService) Available

Available lists the available map layers.

func (*MapLayersService) Data

func (s *MapLayersService) Data(ctx context.Context, layers string, opts *MapLayerOptions) (json.RawMessage, error)

Data returns data for the named layer(s) (for example "hospitals" or "stations"). The response schema is not yet modeled, so raw JSON is returned.

func (*MapLayersService) Stations

func (s *MapLayersService) Stations(ctx context.Context, agencyID, vrid string) (*StationsResponse, error)

Stations returns the fire stations for an agency, decoded from the "stations" map layer.

type NotificationsService

type NotificationsService struct {
	// contains filtered or unexported fields
}

NotificationsService covers push-notification test endpoints.

func (*NotificationsService) SendTestFCM

func (s *NotificationsService) SendTestFCM(ctx context.Context, deviceID string, opts *TestFCMOptions) (json.RawMessage, error)

SendTestFCM fires a test FCM push to a device. The response schema is not yet modeled, so raw JSON is returned.

type Option

type Option func(*Client) error

Option configures a Client. Options are applied in order by NewClient.

func WithAPIKey

func WithAPIKey(key string) Option

WithAPIKey sets the API key sent as the "apikey" query parameter on every request. It is required.

func WithBaseURL

func WithBaseURL(raw string) Option

WithBaseURL sets the API base URL, including the scheme, host, and any version path segment (for example "https://example.invalid/v1"). It is required. The value is parsed and validated; a trailing slash is normalized so relative endpoint paths resolve correctly.

func WithBasicAuth

func WithBasicAuth(user, pass string) Option

WithBasicAuth sets HTTP Basic authentication credentials sent on every request. It is optional.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient sets the underlying *http.Client used for requests. It is optional; a client with default settings is used otherwise.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent overrides the User-Agent header sent on every request.

type PinIcon

type PinIcon struct {
	ID             string `json:"ID"`
	PinImage       string `json:"PinImage"`
	RelativeOffset string `json:"RelativeOffset"`
}

PinIcon is a pin style used to render a map layer.

type RadioStream

type RadioStream struct {
	Name        string `json:"Name"`
	Description string `json:"Description"`
	URL         string `json:"URL"`
}

RadioStream is a live radio feed listed in an agency's live_radio field.

type RegionStringsResponse

type RegionStringsResponse struct {
	RegionStrings map[string]string `json:"RegionStrings"`
}

RegionStringsResponse is the envelope returned by the region-strings endpoint. RegionStrings is a map of region key to value (for example {"ETN": "911"}).

type ResponderService

type ResponderService struct {
	// contains filtered or unexported fields
}

ResponderService covers verified-responder endpoints.

func (*ResponderService) RegisterVerified

func (s *ResponderService) RegisterVerified(ctx context.Context, body any) (json.RawMessage, error)

RegisterVerified registers the device as a known/verified responder. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

func (*ResponderService) UpdateProfileImage

func (s *ResponderService) UpdateProfileImage(ctx context.Context, body any) (json.RawMessage, error)

UpdateProfileImage uploads a verified-responder profile image. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

type SearchAgenciesResponse

type SearchAgenciesResponse struct {
	SearchAgencies []AgencySearchResult `json:"searchagencies"`
}

SearchAgenciesResponse is the envelope returned by the agency search/list endpoints.

type SettingsService

type SettingsService struct {
	// contains filtered or unexported fields
}

SettingsService covers per-device settings and application-status endpoints.

func (*SettingsService) ApplicationStatus

func (s *SettingsService) ApplicationStatus(ctx context.Context, body any) (json.RawMessage, error)

ApplicationStatus performs an app status / min-version / kill-switch check. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

func (*SettingsService) Get

func (s *SettingsService) Get(ctx context.Context, deviceID string) (json.RawMessage, error)

Get returns the per-device settings blob. The response schema is not yet modeled, so raw JSON is returned.

func (*SettingsService) GetApp

func (s *SettingsService) GetApp(ctx context.Context, deviceID string) (json.RawMessage, error)

GetApp returns the app settings for a device. The response schema is not yet modeled, so raw JSON is returned.

func (*SettingsService) Update

func (s *SettingsService) Update(ctx context.Context, body any) (json.RawMessage, error)

Update updates the per-device settings. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

func (*SettingsService) UpdateApp

func (s *SettingsService) UpdateApp(ctx context.Context, deviceID string, body any) (json.RawMessage, error)

UpdateApp updates the app settings for a device. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

type Station

type Station struct {
	ID                string          `json:"ID"`
	ItemID            string          `json:"ItemID"`
	ItemName          string          `json:"ItemName"`
	AgencyID          string          `json:"AgencyID"`
	Icon              string          `json:"Icon"`
	LatitudeLongitude string          `json:"LatitudeLongitude"`
	SortKey           string          `json:"SortKey"`
	Attachments       json.RawMessage `json:"Attachments,omitempty"`
	Info              json.RawMessage `json:"Info,omitempty"`
	OtherMetadata     json.RawMessage `json:"OtherMetadata,omitempty"`
}

Station is a fire station (or other point) in the "Stations" map layer. Attachments, Info, and OtherMetadata have variable shapes and are left raw.

func (Station) LatLng

func (st Station) LatLng() (lat, lng float64, err error)

LatLng parses the station's "lat,lng" LatitudeLongitude field.

type StationsResponse

type StationsResponse struct {
	Layers struct {
		Stations []Station `json:"Stations"`
	} `json:"Layers"`
}

StationsResponse is the envelope returned when requesting the stations layer.

type StatusResponse

type StatusResponse struct {
	StatusCode        string `json:"StatusCode"`
	StatusDescription string `json:"StatusDescription"`
}

StatusResponse is the status envelope the API returns for empty results and many error responses, for example:

{"StatusCode":"200","StatusDescription":"No data exists for query."}

The codes are returned as strings. See APIError.StatusResponse for decoding error bodies into this shape.

type SurveysService

type SurveysService struct {
	// contains filtered or unexported fields
}

SurveysService covers device survey endpoints.

func (*SurveysService) Clear

func (s *SurveysService) Clear(ctx context.Context, deviceID string) (json.RawMessage, error)

Clear marks a device's pending survey complete (dismisses it). The response schema is not yet modeled, so raw JSON is returned.

func (*SurveysService) Get

func (s *SurveysService) Get(ctx context.Context, deviceID string) (json.RawMessage, error)

Get returns the pending survey for a device. The response schema is not yet modeled, so raw JSON is returned.

type TestFCMOptions

type TestFCMOptions struct {
	// DryRun, when true, sends dry_run=1 (do not actually deliver).
	DryRun bool
	// Type is an optional notification type.
	Type string
}

TestFCMOptions holds optional parameters for a test FCM notification.

type Unit

type Unit struct {
	UnitID         string `json:"UnitID"`
	DispatchStatus string `json:"PulsePointDispatchStatus"`
}

Unit is a dispatched unit on an incident. Decode DispatchStatus via the unit legend endpoint (see UnitsService.Legend).

type UnitGroup

type UnitGroup struct {
	GroupID                     int               `json:"groupID"`
	GroupLabel                  string            `json:"groupLabel"`
	AgencyID                    string            `json:"agencyID"`
	SortOrder                   int               `json:"sortOrder"`
	Units                       []string          `json:"units"`
	Tags                        []json.RawMessage `json:"tags"`
	Restricted                  bool              `json:"restricted"`
	ResponderHasOverlappingTags bool              `json:"responderHasOverlappingTags"`
}

UnitGroup is a named grouping of units for an agency. Unlike most of this API, groupID and sortOrder are returned as real JSON numbers. Tags always appeared empty in observed data, so its element shape is left raw.

type UnitGroupSubscriptions

type UnitGroupSubscriptions struct {
	Groups         []json.RawMessage `json:"groups"`
	OnDuty         bool              `json:"onDuty"`
	SendAsCritical bool              `json:"sendAsCritical"`
}

UnitGroupSubscriptions is a device's unit-group push subscription state. The element shape of Groups is left raw (always empty in observed data).

type UnitGroupsResponse

type UnitGroupsResponse struct {
	Groups []UnitGroup `json:"groups"`
}

UnitGroupsResponse is the envelope returned by the unit-groups endpoint.

type UnitLegendEntry

type UnitLegendEntry struct {
	UnitKey     string `json:"UnitKey"`
	Description string `json:"Description"`
	Link        string `json:"Link"`
}

UnitLegendEntry decodes a single unit dispatch code for an agency.

type UnitLegendResponse

type UnitLegendResponse struct {
	UnitLegend []UnitLegendEntry `json:"UnitLegend"`
}

UnitLegendResponse is the envelope returned by the unit-legend endpoint.

type UnitsService

type UnitsService struct {
	// contains filtered or unexported fields
}

UnitsService covers unit legend, groups, and subscription endpoints.

func (*UnitsService) GetSubscriptions

func (s *UnitsService) GetSubscriptions(ctx context.Context, deviceID string) (*UnitGroupSubscriptions, error)

GetSubscriptions returns a device's unit-group push subscriptions.

func (*UnitsService) Groups

func (s *UnitsService) Groups(ctx context.Context, agencyIDs, token string) (*UnitGroupsResponse, error)

Groups returns the unit groups for one or more agencies (comma-separated codes), optionally filtered by a free-text token.

func (*UnitsService) Legend

func (s *UnitsService) Legend(ctx context.Context, agencyID string) (*UnitLegendResponse, error)

Legend returns the unit dispatch-status legend for an agency (decodes status codes such as ER/AR).

func (*UnitsService) UpdateSubscriptions

func (s *UnitsService) UpdateSubscriptions(ctx context.Context, body any) (json.RawMessage, error)

UpdateSubscriptions updates a device's unit-group subscriptions. The request-body schema is not yet verified, so an arbitrary JSON-encodable body is accepted and raw JSON is returned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL