Super Duper Feeder Documentation

Guide to using the feed subscription and webhook delivery service

Introduction

Super Duper Feeder is a service designed to subscribe to RSS/Atom feeds on your behalf. It utilizes WebSub/PubSubHubbub for real-time updates when available by subscribing to the feed's external hub, or falls back to periodic polling otherwise.

Feed updates received (either via WebSub push or polling) can be delivered directly to your own application via a configured webhook URL.

This documentation provides detailed information about the service's API endpoints, webhook usage, and callback verification process.

WebSub Concepts

WebSub (formerly PubSubHubbub) is a protocol that enables real-time notifications for content updates. It involves three main components:

The flow works as follows:

  1. A subscriber (like Super Duper Feeder) discovers the hub URL from a publisher's feed.
  2. The subscriber sends a subscription request to the external hub.
  3. The hub verifies the subscription request with the subscriber (using the `/callback/:id` endpoint of Super Duper Feeder).
  4. When the publisher updates content, they notify their designated hub.
  5. The hub fetches the updated content and sends it to all its verified subscribers (including Super Duper Feeder).
  6. Super Duper Feeder receives the update and forwards it to any developer-registered webhooks for that feed.

API Reference

Webhook Subscription Endpoint

POST /api/webhook

Use this endpoint to subscribe Super Duper Feeder to a feed URL (topic). You can optionally provide your own webhook URL (callback) where you want feed updates delivered.

The service will attempt to discover an external WebSub hub for the specified feed and subscribe to it for real-time updates. If no external hub is found, the service will fall back to periodically polling the feed for new content.

Request Parameters
Parameter Type Required Description
topic string Yes The URL of the feed to subscribe to. This can be an RSS, Atom, or JSON feed, or an HTML page with feed autodiscovery links.
callback string No Your callback URL where updates will be forwarded.
Callback Verification

Important: When you provide a callback URL, it must be verified before any updates are sent to it. This ensures that you actually own the callback URL and prevents abuse.

The verification process works as follows:

  1. You submit a webhook subscription with your callback URL
  2. The system generates a verification token and sends a GET request to your callback URL with the token
  3. Your callback endpoint must respond with the token in the response body
  4. Once verified, your callback will start receiving updates

The verification request will be sent to:

GET {your-callback-url}?mode=verify&token={verification-token}

Your callback endpoint should:

  1. Extract the token from the token query parameter
  2. Respond with a 200 OK status code
  3. Return the token as plain text in the response body

Example callback handler for verification:

// Example using Express.js
app.get('/my-callback', (req, res) => {
  // Check if this is a verification request
  if (req.query.mode === 'verify' && req.query.token) {
    // Return the token as plain text
    res.type('text/plain').send(req.query.token);
  } else {
    // Handle other requests
    res.status(400).send('Invalid request');
  }
});

Verification tokens expire after 24 hours. If your callback is not verified within this time, you'll need to submit a new subscription request.

Response

Status Code: 202 Accepted on success, 400 Bad Request on error, 500 Internal Server Error on server error

Response Body (JSON):

{
  "success": true|false,
  "message": "Description of the result",
  "usingExternalHub": true|false,
  "subscriptionId": "uuid-of-subscription",
  "callbackId": "uuid-of-callback", // Only if callback was provided
  "pendingVerification": true|false, // Indicates if the callback needs verification
  "verificationInstructions": "Instructions for verifying the callback" // Only if pendingVerification is true
}
Success Response Fields
Field Type Description
success boolean Indicates if the subscription request was successful
message string A human-readable description of the result
usingExternalHub boolean Indicates if an external WebSub hub was found and used (true) or if the service fell back to polling (false).
subscriptionId string The UUID of the created subscription, useful for tracking
callbackId string The UUID of the created callback, only present if a callback URL was provided
pendingVerification boolean Indicates if the callback URL requires verification (true) or is already verified (false)
verificationInstructions string Instructions for verifying the callback URL, only present if pendingVerification is true
Error Responses
Status Code Error Message Description
400 Missing topic parameter The required topic parameter was not provided
400 Failed to add feed for polling The service could not add the feed for polling (when using fallback hub)
500 Internal server error: [error details] An unexpected error occurred on the server
Example Usage
// Using fetch API in JavaScript
async function subscribeToFeed(topicUrl, callbackUrl) {
  const formData = new FormData();
  formData.append('topic', topicUrl);
  
  if (callbackUrl) {
    formData.append('callback', callbackUrl);
  }

  const response = await fetch('https://superduperfeeder.deno.dev/api/webhook', {
    method: 'POST',
    body: formData
  });
  
  const result = await response.json();
  
  if (result.success) {
    console.log(`Successfully subscribed to ${topicUrl}`);
    console.log(`Using external hub: ${result.usingExternalHub}`);
    console.log(`Subscription ID: ${result.subscriptionId}`);
    
    if (result.callbackId) {
      console.log(`Callback ID: ${result.callbackId}`);
    }
  } else {
    console.error(`Failed to subscribe: ${result.message}`);
  }
}
Notes
  • The service will automatically discover the WebSub hub for the feed by checking:
    1. HTTP Link headers with rel="hub"
    2. Feed content for hub links
    3. HTML content for hub links or feed autodiscovery links
  • If no external WebSub hub is found, the service will poll the feed directly.
  • If a callback URL is provided and verified, updates (from WebSub or polling) will be forwarded to that URL.
  • WebSub subscriptions initiated by this service have a default lease time and will attempt automatic renewal with the external hub.

Webhook Verification Endpoint

GET /api/webhook/verify/:token

This endpoint is used to manually verify a callback URL. Normally, verification happens automatically when your callback responds to the verification request, but you can also use this endpoint to manually verify a callback if needed.

Path Parameters
Parameter Type Description
token string The verification token sent to your callback URL
Response

Status Code: 200 OK on success, 400 Bad Request on error

Response Body (JSON):

{
  "success": true|false,
  "message": "Description of the result"
}
Success Response
{
  "success": true,
  "message": "Callback verified successfully"
}
Error Responses
{
  "success": false,
  "message": "Invalid verification token"
}

{
  "success": false,
  "message": "Verification token has expired"
}
Notes
  • Verification tokens expire after 24 hours
  • This endpoint is primarily for manual verification or debugging
  • In most cases, your callback should handle the verification request automatically

Internal Callback Endpoint

GET/POST /callback/:id

This endpoint is used **internally** by Super Duper Feeder to handle interactions with **external** WebSub hubs. You typically do not need to interact with this endpoint directly.

External hubs use this endpoint for:

For Verification (GET)

When a hub verifies a subscription, it sends a GET request with the following parameters:

  • hub.mode: Either "subscribe" or "unsubscribe"
  • hub.topic: The feed URL being subscribed to
  • hub.challenge: A challenge string that must be echoed back
  • hub.lease_seconds: (Optional) The subscription duration in seconds
For Content Delivery (POST)

When a hub sends content updates, it sends a POST request with:

  • A Link header containing the topic URL with rel="self"
  • The updated feed content in the request body

The service will forward these updates to any registered callback URLs for the topic.

Health Check

GET /health

Check if the service is running properly.

Usage Examples

Subscribing via API

Use the /api/webhook endpoint to subscribe Super Duper Feeder to a feed and optionally register your callback URL.

// Using fetch API in JavaScript
async function subscribeToFeed(topicUrl, callbackUrl) {
  const formData = new FormData();
  formData.append('topic', topicUrl);

  if (callbackUrl) {
    formData.append('callback', callbackUrl);
  }

  const response = await fetch('https://superduperfeeder.deno.dev/api/webhook', { // Replace with your instance URL if self-hosting
    method: 'POST',
    body: formData
  });

  const result = await response.json();

  if (result.success) {
    console.log(`Successfully initiated subscription for ${topicUrl}`);
    console.log(`Using external hub: ${result.usingExternalHub}`); // True if WebSub hub found, false if polling
    console.log(`Subscription ID: ${result.subscriptionId}`);

    if (result.callbackId) {
      console.log(`Callback ID: ${result.callbackId}`);
      if(result.pendingVerification) {
        console.log("Callback requires verification. Check your callback endpoint for a GET request with ?mode=verify&token=...");
        console.log("Verification Instructions:", result.verificationInstructions);
      } else {
        console.log("Callback is verified.");
      }
    }
  } else {
    console.error(`Failed to subscribe: ${result.message}`);
  }
}

// Example call:
// subscribeToFeed('https://example.com/feed.xml', 'https://my-app.com/webhook');
// subscribeToFeed('https://another-blog.com/rss'); // Without a callback

Handling Callback Verification

If you provide a callback URL when subscribing via /api/webhook, Super Duper Feeder needs to verify that you control that URL. It will send a GET request like this:

GET {your-callback-url}?mode=verify&token={verification-token}

Your endpoint must respond with a 200 OK status and return the exact {verification-token} value as plain text in the response body.

// Example using Express.js
app.get('/my-webhook', (req, res) => {
  // Check if this is a Super Duper Feeder verification request
  if (req.query.mode === 'verify' && req.query.token) {
    console.log(`Received verification request for token: ${req.query.token}`);
    // Return the token as plain text to verify ownership
    res.type('text/plain').status(200).send(req.query.token);
    return;
  }

  // Handle other requests (like receiving actual feed updates via POST)
  res.status(400).send('Invalid request');
});

Receiving Feed Updates at Your Callback

Once your callback is verified (or if you didn't provide one), Super Duper Feeder will forward feed updates it receives (from external WebSub hubs or its own polling) to your registered callback URL via a POST request. The request body will contain the feed update content.

// Example using Express.js (add this to your '/my-webhook' route)
// Make sure to use appropriate body parsing middleware (e.g., express.raw, express.text, express.json depending on expected feed types)
app.post('/my-webhook', express.raw({ type: '*/*' }), (req, res) => { // Use appropriate type or '*/*'
  const feedUpdateContent = req.body.toString(); // Or parse as needed
  const contentType = req.headers['content-type'];

  console.log(`Received feed update (${contentType}):`);
  console.log(feedUpdateContent);

  // --- Process the feed update content here ---
  // Example: Parse XML, extract items, store in database, etc.


  // Acknowledge receipt to Super Duper Feeder
  res.status(200).send('OK');
});

Important: Your endpoint should respond quickly (e.g., within a few seconds) with a 2xx status code to acknowledge receipt. Perform time-consuming processing asynchronously. Failure to respond promptly might cause Super Duper Feeder to consider the delivery failed and retry.

Best Practices

Troubleshooting

Common Issues