Skip to content

Crowdynews API Reference

The Crowdynews API provides programmatic access to content aggregation and publishing features. This documentation covers all available endpoints for discovering collections, retrieving published content, and monitoring content counts.

  1. Discover Collections

    Get a list of available topics for your contract to understand what content is available.

  2. Check Content Count

    Use the count endpoint to see how much content is available or check for new content since your last fetch.

  3. Fetch Content

    Retrieve the actual content items with filtering and pagination options.

All API requests are made to:

Base URL
https://q.crowdynews.com/v1/

Get Collections

Discover available topics and collections for your contract

GET /v1/collections/<contract-name>

Get Content Count

Check how many content items are available or new since last fetch

GET /v1/count/<contract-name>

Get Published Content

Retrieve actual content items with filtering and pagination

GET /v1/content/<contract-name>

Get a list of available collections/topics for a specific contract. Use this endpoint to discover what content topics are available for your contract.

GET https://q.crowdynews.com/v1/collections/<contract-name>
ParameterTypeDescription
contract-nameStringRequired: The slugified name of your contract
[
{
"name": "Premier League",
"type": "breakingburner",
"url": "https://q.crowdynews.com/v1/content/betway?q=premier-league"
},
{
"name": "Chelsea FC",
"type": "breakingburner",
"url": "https://q.crowdynews.com/v1/content/betway?q=chelsea-fc"
}
]
// Get available collections
const response = await fetch('https://q.crowdynews.com/v1/collections/betway');
const collections = await response.json();
console.log('Available topics:', collections.map(c => c.name));
// Output: ['Premier League', 'Chelsea FC']

Get the number of published content items for a specific collection. This endpoint is essential for efficient content management - use it to check for new content before fetching full data.

GET https://q.crowdynews.com/v1/count/<contract-name>
ParameterTypeDescription
contract-nameStringRequired: The slugified name of your contract
ParameterTypeDescription
qStringRequired: The slugified topic name (from collections API)
serviceStringOptional: Filter by service (twitter, youtube, instagram, rss)
sinceIntegerOptional: Unix timestamp - show content after this time
untilIntegerOptional: Unix timestamp - show content until this time
typeStringOptional: Filter by content type (image, video, status, link, embed)
{
"count": "256"
}
// Store the timestamp of your last content fetch
const lastFetchTime = Math.floor(Date.now() / 1000) - 3600; // 1 hour ago
// Check how many new items are available
const countResponse = await fetch(
`https://q.crowdynews.com/v1/count/betway?q=premier-league&since=${lastFetchTime}`
);
const result = await countResponse.json();
if (parseInt(result.count) > 0) {
console.log(`${result.count} new items available since last fetch`);
// Now fetch the actual content using the content API with the same 'since' parameter
fetchNewContent(lastFetchTime);
} else {
console.log('No new content available');
}

Retrieve published content items for a specific topic. This is the main endpoint for getting actual content data.

GET https://q.crowdynews.com/v1/content/<contract-name>
ParameterTypeDescription
contract-nameStringRequired: The slugified name of your contract
ParameterTypeDescription
qStringRequired: The slugified topic name (from collections API)
serviceStringOptional: Filter by service (twitter, youtube, instagram, rss)
sinceIntegerOptional: Unix timestamp - content published after this time
untilIntegerOptional: Unix timestamp - content published until this time
countIntegerOptional: Number of results (1-100, default: 20)
offsetIntegerOptional: Pagination offset (default: 0)
orderStringOptional: Sort order (asc, desc, default: desc)
typeStringOptional: Filter by content type (image, video, status, link, embed)
[
{
"id": "6fc9c511ab95bbd83f8478437a2f87ff1fc4f365",
"service": "rss",
"type": "link",
"title": "Premier League fixture rescheduled",
"text": "Our forthcoming Premier League fixture against Burnley has been rescheduled",
"url": "https://www.arsenal.com/news/premier-league-fixture-rescheduled-0",
"date": "2022-01-09T17:10:00.000Z",
"author": {
"name": "arsenal",
"username": "arsenal"
},
"media": [
{
"type": "image",
"url": "https://www.arsenal.com/sites/default/files/styles/desktop_16x9/public/images/DSC_2115_2021050642150098.JPG?itok=-0Af-IiL"
}
],
"kudos": {
"score": 0,
"rss_score": 0
},
"language": "en"
}
]
PropertyTypeDescription
idStringUnique identifier for the content item
serviceStringSource platform (twitter, youtube, instagram, rss)
typeStringContent type (video, image, link, status, embed, comment)
titleStringContent title (may not be available for all content types)
textStringContent text/description (may contain HTML)
tagsArrayArray of content tags
urlStringURL to original content on source platform
dateDateTimePublication date in ISO 8601 format
authorObjectAuthor information with name and username
mediaArrayAttached media (images, videos, embeds)
locationObjectGeographic location data (if available)
kudosObjectEngagement metrics (likes, shares, etc.)
languageStringContent language (ISO 639-1 code)
stateStringPublication state (published, unpublished)
childrenArrayRelated content items (comments, replies, etc.)

Here’s a complete example showing the recommended workflow for efficiently working with the Crowdynews API:

  1. Discover Available Topics

    // Get all available collections for your contract
    const collectionsResponse = await fetch('https://q.crowdynews.com/v1/collections/your-contract');
    const collections = await collectionsResponse.json();
    console.log('Available topics:');
    collections.forEach(collection => {
    console.log(`- ${collection.name}`);
    });
  2. Check for New Content (Efficient)

    // Check if there's new content since your last fetch
    const lastFetchTime = getLastFetchTimestamp(); // Your stored timestamp
    const topic = 'premier-league'; // Choose your topic
    const countResponse = await fetch(
    `https://q.crowdynews.com/v1/count/your-contract?q=${topic}&since=${lastFetchTime}`
    );
    const countResult = await countResponse.json();
    if (parseInt(countResult.count) > 0) {
    console.log(`${countResult.count} new items available`);
    // Proceed to fetch content
    }
  3. Fetch New Content

    // Fetch only new content using the same 'since' parameter
    const contentResponse = await fetch(
    `https://q.crowdynews.com/v1/content/your-contract?q=${topic}&since=${lastFetchTime}&count=50`
    );
    const newContent = await contentResponse.json();
    // Process your content
    newContent.forEach(item => {
    console.log(`New ${item.service} ${item.type}: ${item.title}`);
    });
    // Update your last fetch timestamp
    saveLastFetchTimestamp(Math.floor(Date.now() / 1000));

For large result sets, use pagination:

async function fetchAllContent(contractName, topic, since = null) {
let allContent = [];
let offset = 0;
const limit = 100; // Maximum per request
while (true) {
let url = `https://q.crowdynews.com/v1/content/${contractName}?q=${topic}&count=${limit}&offset=${offset}`;
if (since) url += `&since=${since}`;
const response = await fetch(url);
const content = await response.json();
if (content.length === 0) break; // No more content
allContent.push(...content);
offset += limit;
// Break if we got less than the limit (last page)
if (content.length < limit) break;
}
return allContent;
}

Error Response Format

All error responses include a requestId and an errors array with detailed error information.

{
"requestId": "request-uuid",
"errors": [
{
"name": "ErrorType",
"message": "Error description",
"propertyName": "field_name",
"propertyValue": "field_value",
"reason": "Additional details",
"code": 1001
}
]
}

Common Errors

  • NotFoundError: Unknown topic or collection
  • ValidationError: Invalid parameters
  • RateLimitError: Too many requests
  • AuthenticationError: Invalid contract name
async function fetchContentSafely(contractName, topic) {
try {
const response = await fetch(`https://q.crowdynews.com/v1/content/${contractName}?q=${topic}`);
if (!response.ok) {
const errorData = await response.json();
console.error('API Error:', errorData.errors[0].message);
return null;
}
return await response.json();
} catch (error) {
console.error('Network Error:', error.message);
return null;
}
}

Twitter

Brand Toolkit

Twitter Brand Guidelines →

  • Use official Twitter logo and colors
  • Include proper attribution
  • Link back to original tweets

YouTube

Developer Guidelines

YouTube Branding Guidelines →

  • Use official YouTube logo and play button
  • Include video attribution
  • Display accurate metadata

When displaying content, ensure:

  • ✅ Official logos are used correctly
  • ✅ Proper attribution is included
  • ✅ Links back to original content work
  • ✅ Brand colors match official guidelines
  • ✅ Required disclaimers are present
  • ✅ Terms of service are followed

  1. Check counts first: Always use the count endpoint to determine if new content is available
  2. Use timestamps: Leverage since parameters to fetch only new content
  3. Implement caching: Cache responses locally to reduce API calls
  4. Batch requests: Use maximum count values (100) to minimize request numbers
  5. Handle errors gracefully: Implement retry logic with exponential backoff