Assets

These endpoints manage the files an app's templates draw: Rive animations and images. Upload a file, list what an app has, and delete what you do not need. The examples use the $HERALD and $TOKEN variables from Connect.

What an asset is#

An asset is a file Herald keeps for one app so that its templates can use it. There are two kinds.

KindUsed byStored as
Rive animationThe rive component.assets/<app>/<id>.riv in Herald's support folder.
ImageThe image component, as a fixed picture or a field value.assets/<app>/images/<name>.

A notification can already carry a picture in its image field. Upload an image as an asset when the same picture is part of the design, such as a logo, and should not be sent with every notification.

Rive files can also be declared in the app's manifest, which installs them when the manifest is saved. Uploading here is the direct way and needs no manifest.

Endpoints#

EndpointPurpose
GET /v1/assetsList an app's Rive files and images.
POST /v1/assetsUpload a Rive file or an image.
DELETE /v1/assetsDelete one file.

GET /v1/assets#

Lists the Rive files and images stored for one app, and for each Rive file which templates use it.

Request

NameInTypeRequiredDescription
appquerystringrequiredThe app whose assets to list.
Example requestshell
curl -s "$HERALD/v1/assets?app=example.bidbot" -H "Authorization: Bearer $TOKEN"
Example responseJSON
{
  "app": "example.bidbot",
  "folder": "/Users/you/Library/Application Support/Herald/assets/example.bidbot",
  "limits": {"bytes": 10485760, "riveFiles": 32},
  "assets": [
    {
      "kind": "rive",
      "id": "confetti",
      "file": "confetti.riv",
      "path": "/Users/you/Library/Application Support/Herald/assets/example.bidbot/confetti.riv",
      "bytes": 48211,
      "declared": false,
      "usedBy": ["bid-accepted"],
      "component": {"type": "rive", "path": "confetti.riv"}
    },
    {
      "kind": "image",
      "file": "logo.png",
      "path": "/Users/you/Library/Application Support/Herald/assets/example.bidbot/images/logo.png",
      "bytes": 9120
    }
  ]
}

Response fields

FieldTypeDescription
folderstringThe app's asset folder.
limitsobjectThe largest file in bytes, and how many Rive files an app may hold.
assets[].kindstringrive or image.
assets[].filestringThe file name. Use it with DELETE /v1/assets.
assets[].pathstringThe full path of the stored file.
assets[].bytesintegerThe file size.
assets[].idstringRive only: the asset id, which is the file name without .riv.
assets[].declaredbooleanRive only: true when the app's manifest declares this file.
assets[].usedByarrayRive only: the templates that play this animation.
assets[].componentobjectRive only: a ready rive component that plays this file.

Errors

StatusWhen
400app is missing.

POST /v1/assets#

Stores a Rive animation or an image for an app. Uploading a file with the name of an existing one replaces it.

Request

Give the file in exactly one of two ways: path for a file that is already on this Mac, or base64 for content sent in the request.

NameInTypeRequiredDescription
appbodystringrequiredThe app that will own the file.
pathbodystringoptionalA file on this Mac. ~ is expanded.
base64bodystringoptionalThe file's bytes as base64. Requires name.
namebodystringoptionalThe file name to store, such as logo.png. Default with path: the file's own name.
kindbodystringoptionalrive or image. Default: decided from the file extension.
Example requestshell
curl -s -X POST "$HERALD/v1/assets" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"app": "example.bidbot", "path": "~/Designs/confetti.riv"}'
Example responseJSON
{
  "ok": true,
  "kind": "rive",
  "app": "example.bidbot",
  "id": "confetti",
  "file": "confetti.riv",
  "path": "/Users/you/Library/Application Support/Herald/assets/example.bidbot/confetti.riv",
  "bytes": 48211,
  "replaced": false,
  "component": {"type": "rive", "path": "confetti.riv"}
}

Response fields

FieldTypeDescription
kindstringrive or image.
filestringThe stored file name.
pathstringThe full path of the stored file. For an image, use it as an image value.
bytesintegerThe stored size.
replacedbooleantrue when a file with this name existed and was overwritten.
idstringRive only: the asset id to use in a rive component.
componentobjectRive only: a ready rive component that plays this file.
formatstringImage only: the detected format, such as png.

Errors

StatusWhen
400Both or neither of path and base64 were sent, or name is missing with base64.
400The file does not exist, is empty, or its name contains a folder.
400The kind cannot be decided from the name, or the bytes are not an image Herald can draw.
413The file is larger than 10 MB.
429The app already holds 100 images.

Notes

  • A request body is limited to 1 MB, so base64 suits files up to about 700 KB. Use path for anything larger.
  • Images are checked by their bytes, not their names. PNG, JPEG, GIF, WebP, HEIC, TIFF and BMP are accepted.
  • An app can hold 32 Rive files and 100 images, each up to 10 MB.

DELETE /v1/assets#

Deletes one stored file. Templates are not changed, so the reply tells you which templates still refer to a deleted animation.

Request

NameInTypeRequiredDescription
appquerystringrequiredThe app that owns the file.
filequerystringrequiredThe file name from GET /v1/assets, such as confetti.riv.
Example requestshell
curl -s -X DELETE "$HERALD/v1/assets?app=example.bidbot&file=confetti.riv" \
  -H "Authorization: Bearer $TOKEN"
Example responseJSON
{"ok": true, "deleted": "confetti.riv", "stillReferencedBy": ["bid-accepted"]}

Errors

StatusWhen
400app or file is missing, or file is not a .riv or image file name.
404The app has no file with this name.

Notes

  • A template that plays a deleted animation draws a labelled placeholder in its place.

Edit this page on GitHub

Esc
Getting started
Guides