REST API

Base URL: https://nesh.kkweb.io/api/v1/projects/<projectId>

Subscribe

Called by the SDK after the browser issues a push subscription. CORS-enabled, no auth.

POST /api/v1/projects/<projectId>
Content-Type: application/json

{
  "endpoint": "https://fcm.googleapis.com/...",
  "keys": { "p256dh": "...", "auth": "..." },
  "userId": "alice"            // optional
}

→ 201 { "ok": true }

Rate limited 60 / minute per IP × project × action. The endpoint also enforces the free-tier subscriber cap on new endpoints (existing endpoints can always update).

Unsubscribe

DELETE /api/v1/projects/<projectId>?endpoint=<urlencoded-endpoint>

→ 200 { "ok": true }

Send notification

Server-to-server. Use the Bearer token from the project's API key card (format nesh_sk_…). Synchronous — the response includes delivery counts.

POST /api/v1/projects/<projectId>/notifications
Authorization: Bearer nesh_sk_…
Content-Type: application/json

{
  "title":   "Hello",
  "body":    "From the API",
  "url":     "https://example.com",
  "icon":    "https://example.com/icon-192.png",
  "image":   "https://example.com/hero.jpg",
  "badge":   "https://example.com/badge-72.png",
  "userIds": ["alice", "bob"]    // optional — omit to broadcast
}

→ 201 {
  "id":        "uuid",
  "attempted": 12,
  "delivered": 11,
  "removed":   1,
  "failed":    0
}

Subject to the monthly send cap (10,000 / project / UTC month on the free tier). Returns 429 when reached.

Track event (SDK / SW)

Service Workers POST shown / clicked beacons here automatically when the SDK is v0.6+. You shouldn't normally call this from your code.

POST /api/v1/projects/<projectId>/notifications/<notificationId>/events
Content-Type: application/json

{ "type": "shown" }   // or "clicked"

→ 200 { "ok": true }