Publishing releases
Publish from the API, from CI, or automatically from GitHub releases.
Via the API
curl -X POST https://relayer-three.vercel.app/api/v1/releases \
-H "Authorization: Bearer rl_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"app": "YOUR_APP_REF",
"channel": "stable",
"version": "1.4.2",
"notes": "markdown release notes",
"artifacts": [{
"platform": "windows",
"arch": "x86_64",
"url": "https://your-storage/…/setup.exe",
"sha512": "optional integrity hash",
"size": 48234496,
"signature": "optional (e.g. Tauri minisign)"
}]
}'Works from any CI. Versions are unique per app+channel (409 on duplicates, so retried CI jobs are safe). See the API reference for all endpoints.
Via GitHub releases
Keep your existing flow - gh release create v2.1.0 ./dist/* - and let the
webhook do the rest.
Setup: on your app's Settings tab, click Connect under GitHub
releases, then in your repo: Settings → Webhooks → Add webhook → paste the
payload URL and secret → content type application/json → select only the
Releases event.
Behavior:
- Pre-releases land on
beta, normal releases onstable. - The tag (minus a leading
v) becomes the version; the release body becomes the notes. - Assets are classified by filename into platform/arch (works with
electron-builder, Tauri, GoReleaser and common naming schemes); checksum
and metadata files (
.sig,.yml,SHA256SUMS, …) are excluded. - Drafts are ignored; GitHub's retry deliveries are answered as duplicates, never double-ingested.
- Every delivery is HMAC-verified (SHA-256, timing-safe).
Test without a repo
Any correctly-signed POST is a valid delivery - sign one yourself with your
webhook secret and openssl:
SECRET="<webhookSecret>" # app Settings → GitHub releases
BODY='{"action":"published","repository":{"full_name":"you/app"},"release":{"id":1,"tag_name":"v1.2.0","name":"v1.2.0","body":"## Notes","draft":false,"prerelease":false,"html_url":"https://github.com/you/app/releases/tag/v1.2.0","assets":[{"name":"myapp-1.2.0-darwin-aarch64.dmg","browser_download_url":"https://example.com/myapp-1.2.0.dmg","size":52428800,"content_type":"application/octet-stream"}]}}'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')"
curl -X POST <payload-url> \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: release" \
-H "X-Hub-Signature-256: $SIG" \
-d "$BODY"