Transport for the CFPB Consumer Complaint Database API: the settings resolver (per-call opts first, then context variables, then defaults), a typed HttpError, JSON GETs, and query-string building that drops unset values and repeats a key for a Vec value.

opts keyContext variableDefault
base-urlcfpb.complaints.base-urlhttps://www.consumerfinance.gov/data-research/consumer-complaints/search/api/v1

The API takes no credential, so a per-call base-url needs none.

Context Vars

Optional
  • cfpb.complaints.base-url

Values

BASE_URL

BASE_URL: Str "https://www.consumerfinance.gov/data-research/consumer-complaints/search/api/v1"

PACKAGE_AGENT

PACKAGE_AGENT: Str "hot-dev-cfpb-complaints-pkg/0.1 (+https://hot.dev)"

SOURCE

SOURCE: Str "cfpb-complaints"

Functions

body-detail

fn (body: Any): Str?

clip

fn (text: Str): Str

decode-body

fn (response: ::hot::http/HttpResponse, url: Str): Any

The decoded JSON of a 2xx response, or an Err carrying HttpError when the body is not JSON (pure). Exposed for testing.

get-json

fn (url: Str, headers: Map): Any

GET a JSON resource and return the decoded body, or an Err carrying HttpError.

given

fn (v: Any): Bool

True for a non-null value that is not a blank string or an empty Vec.

http-error

fn (response: ::hot::http/HttpResponse, url: Str): HttpError

Build an HttpError from a non-2xx response. Exposed for testing; every request uses it.

not-json-error

fn (response: ::hot::http/HttpResponse, url: Str): HttpError

An HttpError for a 2xx response that is not JSON. consumerfinance.gov answers an unknown API path with its HTML search page and status 200, so a removed route looks like success. Exposed for testing.

path-segment

fn (value: Any): Str

Percent-encode one path segment.

pick

fn (opts: Map, key: Str, ctx-key: Str, default: Any): Any

query-pairs

fn (key: Str, value: Any): Vec<Str>

query-string

fn (params: Map): Str

Build a ?a=1&b=2 suffix from a Map, dropping null, blank and empty values (pure); "" when nothing remains. A Vec value repeats the key: {state: ["CA", "NY"]} gives ?state=CA&state=NY.

request

fn (method: Str, url: Str, headers: Map): ::hot::http/HttpResponse

GET (or another method) a CFPB URL with headers, returning the HttpResponse on 2xx or an Err carrying HttpError. A transport failure passes through as its own Err.

resolve

fn (opts: Map): Map

Resolve settings for one call: {base-url}. A value in opts wins over context.

Example

cfg ::cfpb::complaints::api/resolve({base-url: "https://ccdb-proxy.example/api/v1"})

retry-after

fn (headers: Map): Int?

strip-slash

fn (url: Str): Str

Types

HttpError

HttpError type {
    source: Str,
    status: Int,
    url: Str,
    headers: Map,
    body: Any,
    retry-after: Int?,
    message: Str
}

A failed CFPB response. source is "cfpb-complaints"; url the requested URL (the API takes no credentials in URLs); retry-after the parsed Retry-After seconds on 429s; message a one-line summary. status is normally non-2xx, but it is 200 when the site answered with something other than JSON (see get-json).