Repository navigation
ntfy
Typed ntfy client for Deno, Bun, Node.js and Cloudflare Workers. Publish push notifications to a topic on ntfy.sh or a self-hosted ntfy server, with optional auth for protected topics.
ntfy is an open, HTTP-based pub-sub protocol: publish a message to a topic,
and anyone subscribed to that topic gets notified. Topics on the public
https://ntfy.sh instance need no account and no credentials — pick a
topic name and start publishing. This connect exposes a single method,
publish(), covering ntfy's JSON publish form (POST /), which is a strict
superset of the plain-text POST /<topic> form. It uses RESTler for
transport and Guardian for runtime request/response validation.
import { Ntfy } from '@tundraconnect/ntfy';
// No account, no API key — just pick a topic and publish.
const client = new Ntfy();
await client.publish({ topic: 'mytopic', message: 'Hello from ntfy!' });Your tests don't need to fake HTTP. Have your code take a Ntfy instance
and pass in a stand-in that returns the shapes from
@tundraconnect/ntfy/schemas or throws a real NtfyError:
import { NtfyError } from '@tundraconnect/ntfy/errors';
const outage = new NtfyError('SERVICE_UNAVAILABLE', { status: 503 });
console.log(outage.code);To exercise the client itself against a fake transport, subclass it and
reassign the protected _fetch.
| Topic | Description |
|---|---|
| API | Client configuration and endpoint methods |
| Errors | Error codes and diagnostic metadata |
| Schemas | Public Guardian schemas and inferred types |
Deno:
deno add jsr:@tundraconnect/ntfyBun:
bunx jsr add @tundraconnect/ntfyNode.js:
npx jsr add @tundraconnect/ntfyimport { Ntfy } from '@tundraconnect/ntfy';
const client = new Ntfy();
const message = await client.publish({
topic: 'mytopic',
title: 'Disk space alert',
message: 'Disk usage on server1 is at 90%',
priority: 4,
tags: ['warning', 'floppy_disk'],
});
console.log(message.id);Publishing to a protected topic, or against a self-hosted instance, only
needs auth/baseURL — both plain RESTlerOptions fields:
import { Ntfy } from '@tundraconnect/ntfy';
const client = new Ntfy({
baseURL: 'https://ntfy.example.com',
auth: { type: 'BEARER', token: 'tk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' },
});The public https://ntfy.sh instance enforces (as documented, subject to
change): a default request-rate limit of 60 requests burst then 1 per 10s
per visitor, a 4,096-byte message body before ntfy auto-converts it to an
attachment, and a 15 MB max attachment size (100 MB total per visitor,
expiring after 3 hours). See the
ntfy.sh docs for current
numbers — this connect does not enforce them client-side.
MIT. Part of Tundra Connect, typed vendor API clients for Deno, Bun, Node.js and Cloudflare Workers.
- Algolia
- AzureBlob
- CloudflareDNS
- CloudflareEmail
- CloudflareSaaS
- CloudflareTurnstile
- CoinGecko
- Discord
- DodoPayments
- GCS
- GoogleAnalytics
- GoogleCertificateManager
- GoogleWebRisk
- Kalshi
- ntfy
- OpenExchange
- OpenWeatherMap
- PayPal
- Polymarket
- Razorpay
- Resend
- S3
- SendGrid
- Sentry
- Slack
- Stripe
- Telegram
- Twilio
- UpstashRedis
- URLhaus