claude/epic-nobel-5d1572
axios was required by src/utils/message.js and src/utils/webhook.js but was never declared in package.json, so `npm install` never fetched it and the app crashed on startup with MODULE_NOT_FOUND. Switch both webhook POST calls to Node's built-in fetch (available since Node 18; running on 22.12), removing the missing dependency entirely. Behavior is preserved: JSON body with Content-Type header, and an explicit response.ok check to keep axios's throw-on-non-2xx semantics. message.js now returns parsed JSON (or text fallback) in place of axios's response.data. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nostr Post Scheduler & Private Message API
A Node.js API for scheduling Nostr posts and sending private messages using the Nostr protocol.
Features
- Schedule public Nostr posts (kind: 1) at a future time
- Reschedule or cancel scheduled posts
- Send encrypted private messages (kind: 4)
- Auto-managing the database, including table creation and indexing
- Efficient background job processing to send scheduled posts just-in-time
- API key authentication for secure access
- Swagger UI documentation available at
/docsfor easy API exploration
Technology Stack
- Programming Language: JavaScript (Node.js)
- Framework: Express.js
- Database: SQLite (default) or PostgreSQL/MySQL (via .env configuration)
- Queue System: Background tasks with node-cron
- Security: API key authentication, proper key handling, and rate limiting
- Documentation: Swagger UI (
/docs) and Redoc (/redoc) - Nostr Libraries: Nostr-NDK and nostr-tools
Getting Started
Prerequisites
- Node.js (v14 or higher)
- npm or yarn
Installation
- Clone the repository:
git clone https://github.com/yourusername/nostr-scheduler-api.git
cd nostr-scheduler-api
- Install dependencies:
npm install
- Create a
.envfile based on the.env.example:
cp .env.example .env
- Edit the
.envfile with your configuration:
cp .env.example .env
- Start the server:
npm start
For development with auto-reload:
npm run dev
API Documentation
Once the server is running, you can access the API documentation at:
- Swagger UI: http://localhost:3000/docs
API Endpoints
Schedule a Nostr Post
- Method: POST
/schedule/post - Description: Schedules a new Nostr post at a future time.
- Request Parameters:
content: Content of the Nostr post- Either
timestamp(Unix format) or bothdate(DD/MM/YY or DD/MM/YYYY) andhour(HH:MM or HHMM) - Optional
relays(otherwise defaults from .env)
Reschedule a Nostr Post
- Method: PATCH
/schedule/post/{post_id} - Description: Updates the scheduled time of an existing post.
- Request Parameters:
post_id: ID of the post to reschedule- Either new
timestampor newdate+hour
Retrieve a Scheduled Post
- Method: GET
/schedule/post/{post_id} - Description: Returns details of a scheduled post.
Delete a Scheduled Post
- Method: DELETE
/schedule/post/{post_id} - Description: Cancels a scheduled post before it is sent.
List All Scheduled Posts
- Method: GET
/schedule/posts - Description: Returns all pending scheduled posts.
Send a Private Message
- Method: POST
/messages/send - Description: Immediately sends an encrypted private message.
- Request Parameters:
recipient_pubkey: Public key of the recipientcontent: Message content- Optional
relays(otherwise defaults from .env)
Retrieve Sent Messages
- Method: GET
/messages/sent - Description: Returns a history of sent private messages.
Webhook for External Triggers
- Method: POST
/webhook/trigger - Description: Allows an external service to trigger a scheduled post immediately.
- Request Parameters:
post_id: ID of the post to send immediately
Authentication & Security
All API requests require an Admin API Key in the request headers:
- Header:
Authorization: Bearer <ADMIN_API_KEY> - If missing or incorrect, the API returns 401 Unauthorized.
Private Key Handling:
- The private key (in nsec or hex format) is stored in .env and never in the database.
- It is only loaded when necessary for signing events.
Rate Limiting:
- Prevents spam and excessive API usage.
- Limited to X requests per minute (configurable).
Database Schema
Table: scheduled_posts
| Column | Type | Description |
|---|---|---|
| id | INTEGER | Unique ID of the scheduled post (PK) |
| content | TEXT | The content of the scheduled note |
| timestamp | INTEGER | Auto-saved Unix timestamp |
| date | TEXT | Human-readable date (YYYY-MM-DD) |
| hour | TEXT | Human-readable time (HH:MM) |
| relays | TEXT | Comma-separated list of relays |
| status | TEXT | "pending", "sent", or "failed" |
| created_at | INTEGER | Creation timestamp |
| updated_at | INTEGER | Last update timestamp |
Table: sent_messages
| Column | Type | Description |
|---|---|---|
| id | INTEGER | Unique ID of the message (PK) |
| recipient_pubkey | TEXT | The recipient's public key |
| message | TEXT | The message content |
| timestamp | INTEGER | Unix timestamp of when it was sent |
| relays | TEXT | Comma-separated list of relays |
| event_id | TEXT | Event ID of the sent message |
| created_at | INTEGER | Creation timestamp |
License
This project is licensed under the MIT License - see the LICENSE file for details.
Languages
JavaScript
88.9%
CSS
11.1%