Skip to content

Custom API

Turns any JSON API into a card, from YAML alone, with no code. Name a URL and say where the numbers are. It can draw stats, a list, a table or status rows.

config.yaml
integrations:
api:
type: api
url: http://speedtest.example.com/api/latest
title: Speedtest
icon: wifi
about: The last internet speed test.
headers:
Authorization: Bearer ${SPEEDTEST_TOKEN}
stats:
- label: Down
value: download|round:0
unit: Mbps
max: 1000
- label: Up
value: upload|round:0
unit: Mbps
max: 1000
- label: Ping
value: ping
unit: ms
warn: 30
bad: 80
- label: Last run
value: at|ago
layout:
- title: Build
widgets:
- api.data
OptionTypeDefaultWhat it does
urlURLrequiredWhere the service answers, from Valet’s side.
methodGET, POSTGETHow to ask.
headersmap of string{}${SECRETS} go here (or in the url), never in the card
bodyanyoptionalfor POST: text, or anything else is sent as JSON
everynumber or stringoptionalHow often to refresh while someone is looking: seconds, or 30s, 5m, 1h.
titlestringAPIThe card’s title.
iconstringoptionalThe card’s icon, by name.
hrefstringoptionalwhere the card links to
aboutstringoptionaltells the assistant what this is and when to use it
statslist of objectoptionalnumbers: [{ label, value, unit, sub, max, warn, bad }]
stats[].labelstringrequiredThe number’s name.
stats[].valuestringrequiredA path into the response, such as data.speed, with optional formats: size|bytes. A string with braces is a template: {used|bytes} of {total|bytes}.
stats[].unitstringoptionalWritten after the value.
stats[].substringoptionalA second line under it. Same form as value.
stats[].maxnumberoptionalThe full scale, which draws a meter.
stats[].warnnumberoptionalPast this value, it turns to warning. Above is worse, or below when warn is higher than bad, as with free space.
stats[].badnumberoptionalPast this value, it turns to trouble. Same direction as warn.
listobjectoptionalShow rows. Each field below is a path into a row.
list.itemsstring$Where the rows are. $ is the whole response.
list.limitwhole number10How many rows. Range 1 to 100.
list.titlestringrequiredEach row’s title.
list.subtitlestringoptionalEach row’s second line.
list.metastringoptionalWhat sits on the right of each row.
list.imagestringoptionalEach row’s picture.
list.hrefstringoptionalwhere the card links to
list.pctstringoptionalEach row’s progress, 0 to 1.
rowsmap of stringoptionallabel → value, as a table
statusobjectoptionalShow up-or-down rows. Each field below is a path into a row.
status.itemsstring$Where the rows are. $ is the whole response.
status.limitwhole number10How many rows. Range 1 to 100.
status.namestringrequiredEach row’s name.
status.okstringrequiredWhat says it’s up.
status.detailstringoptionalA line under the name.
status.hrefstringoptionalwhere the card links to
status.groupstringoptionalThe heading it sits under.

One widget. Its key is api.data, using the instance name from your config.

api.data · stats card · refreshes every minute while the page is open.

Custom API, Speedtest, medium size
Medium
Custom API, Speedtest, large size
Large
Custom API, Speedtest, in chat
In chat

Small draws the same as medium. Wide draws the same as medium. Tall draws the same as medium, so they aren't shown. Only the empty space changes.

Custom API Speedtest: As a list
As a list
Custom API Speedtest: As a status list
As a status list
Custom API Speedtest: As a table
As a table
Custom API Speedtest: Can't reach it
Can't reach it

What the assistant can use, once its access level allows it. Read tools run freely. Everything else asks first.

ToolAccessWhat it does
readreadThe last internet speed test.