# Cardano Feed API Documentation

Complete reference for the Cardano Feed REST API. All endpoints are public unless otherwise noted.

## Base URL

```
https://cardanofeed.com/api
```

## Authentication

**Most endpoints are completely public with no authentication required.**

Three types of authentication exist:

1. **Public (No Auth)** — All content endpoints (articles, videos, timeline, projects, courses, settings, etc.) require NO authentication.

2. **X-API-Key** — Some internal endpoints require an API key header:
   ```
   X-API-Key: your_api_key_here
   ```
   Contact the administrator to obtain an API key if needed.

3. **Firebase Authentication** — Admin endpoints (`/api/admin/*`) require Firebase user authentication via the frontend application.

## Public Endpoints (No Auth Required)

All of these endpoints are completely public:

✅ Articles (`/api/articles*`)  
✅ Videos (`/api/videos*`)  
✅ Timeline (`/api/timeline`)  
✅ YouTube Channels (`/api/youtube-channels`)  
✅ Sources (`/api/sources`)  
✅ Projects (`/api/projects`)  
✅ Courses (`/api/courses`)  
✅ Settings (`/api/settings`)  
✅ Languages (`/api/languages`)  
✅ Statistics (`/api/stats*`)  
✅ Prices (`/api/prices`, `/api/coingecko/*`)  
✅ Health (`/api/health`)  
✅ Newsletter Subscribe (`/api/newsletter/subscribe`)  
✅ Content Keywords (`/api/content-keywords`)  

---

## Endpoints

### Articles

#### GET `/articles`
Fetch articles with optional filtering and pagination.

**Query Parameters:**
- `limit` (number, default: 50) - Maximum results per page
- `offset` (number, default: 0) - Pagination offset
- `lang` (string) - Filter by language (e.g., 'en', 'pt', 'es')
- `source_id` (number) - Filter by RSS source ID

**Response:**
```json
[
  {
    "id": "uuid",
    "title": "Article Title",
    "slug": "article-url-slug",
    "content": "Article HTML content",
    "summary": "Brief summary",
    "image_url": "https://...",
    "author": "Author Name",
    "source_id": 1,
    "published_at": "2025-06-19T10:30:00Z",
    "updated_at": "2025-06-19T10:30:00Z",
    "view_count": 150,
    "language": "en",
    "status": "published",
    "is_cardano_related": true
  }
]
```

#### GET `/articles/:slug`
Fetch a single article by slug. Supports both short and legacy slug formats.

**Path Parameters:**
- `slug` - Article slug (e.g., `cardano-news-123abc` or `article/cardano-news-123abc-uuid`)

**Response:** Single article object (see above)

#### GET `/articles/:slug/markdown`
Fetch article content as clean Markdown (for AI agents).

**Response:**
```json
{
  "title": "Article Title",
  "markdown": "# Article Title\n\nMarkdown formatted content...",
  "metadata": {
    "published_at": "2025-06-19T10:30:00Z",
    "source": "Source Name",
    "language": "en"
  }
}
```

### Videos

#### GET `/videos`
Fetch YouTube videos.

**Query Parameters:**
- `limit` (number, default: 8) - Results to return
- `lang` (string) - Filter by channel language
- `channel_id` (string) - Filter by YouTube channel ID

**Response:**
```json
[
  {
    "id": "uuid",
    "video_id": "dQw4w9WgXcQ",
    "title": "Video Title",
    "description": "Video description",
    "thumbnail_url": "https://...",
    "channel_id": "youtube_channel_id",
    "published_at": "2025-06-19T10:30:00Z",
    "view_count": 1000,
    "duration": "10:30",
    "language": "en",
    "status": "active",
    "is_cardano_related": true
  }
]
```

#### GET `/videos/latest`
Fetch latest videos.

**Query Parameters:**
- `limit` (number, default: 4)
- `lang` (string)

**Response:** Array of video objects (see above)

### Timeline

#### GET `/timeline`
Fetch combined feed of articles and videos, merged by publish date.

**Query Parameters:**
- `limit` (number, default: 100) - Maximum results
- `lang` (string, default: 'all') - Filter by language

**Response:**
```json
[
  {
    "id": "uuid",
    "type": "article" | "video",
    "title": "Content Title",
    "published_at": "2025-06-19T10:30:00Z",
    "thumbnail": "https://...",
    "slug": "article-slug",
    "video_or_article_id": "uuid or video_id",
    "view_count": 100,
    "author": "Author or null",
    "language": "en",
    "source_name": "Source or Channel Name"
  }
]
```

### Sources (RSS Feeds)

#### GET `/sources`
Fetch all active RSS feed sources.

**Query Parameters:**
- `lang` (string) - Filter by language

**Response:**
```json
[
  {
    "id": 1,
    "name": "Source Name",
    "url": "https://example.com/feed",
    "language": "en",
    "active": true,
    "article_count": 50
  }
]
```

### YouTube Channels

#### GET `/youtube-channels`
Fetch all active YouTube channels.

**Response:**
```json
[
  {
    "id": "uuid",
    "channel_id": "UCxxxxxxxxxx",
    "name": "Channel Name",
    "url": "https://youtube.com/...",
    "language": "en",
    "active": true,
    "subscriber_count": 10000,
    "video_count": 100
  }
]
```

### Projects

#### GET `/projects`
Fetch Cardano ecosystem projects.

**Query Parameters:**
- `limit` (number, default: 100)
- `lang` (string)

**Response:**
```json
[
  {
    "id": "uuid",
    "name": "Project Name",
    "description": "Project description",
    "website": "https://example.com",
    "github": "https://github.com/...",
    "twitter": "https://twitter.com/...",
    "logo_url": "https://...",
    "category": "DApp",
    "status": "active",
    "language": "en"
  }
]
```

### Courses

#### GET `/courses`
Fetch educational courses.

**Query Parameters:**
- `limit` (number, default: 50)

**Response:**
```json
[
  {
    "id": "uuid",
    "title": "Course Title",
    "description": "Course description",
    "instructor_name": "Instructor Name",
    "instructor_avatar": "https://...",
    "duration": "4 weeks",
    "level": "beginner",
    "published_at": "2025-06-19T10:30:00Z"
  }
]
```

### Settings

#### GET `/settings`
Fetch site-wide settings (branding, theme, configuration).

**Response:**
```json
{
  "site_name": "Cardano Feed",
  "site_description": "Description",
  "primary_color": "hsl(220, 90%, 56%)",
  "secondary_color": "hsl(220, 14%, 96%)",
  "logo_url": "https://...",
  "favicon_url": "https://..."
}
```

### Statistics

#### GET `/stats/languages`
Fetch distribution of content by language.

**Response:**
```json
{
  "en": 450,
  "pt": 120,
  "es": 80,
  "fr": 45
}
```

#### GET `/stats/sources`
Fetch article counts by RSS source.

**Response:**
```json
[
  {
    "source_id": 1,
    "source_name": "Source Name",
    "article_count": 150,
    "avg_engagement": 75
  }
]
```

### Languages

#### GET `/languages`
Fetch list of all content languages.

**Response:**
```json
["en", "pt", "es", "fr", "de", "ja"]
```

### Health & Status

#### GET `/health`
Health check endpoint for monitoring.

**Response:**
```json
{
  "status": "ok",
  "time": "2025-06-19T10:30:00Z",
  "db": "connected"
}
```

#### GET `/admin/ingestion/health-public`
Ingestion pipeline status (public).

**Response:**
```json
{
  "rss": {
    "requested_at": "2025-06-19T10:30:00Z",
    "completed_at": "2025-06-19T10:31:00Z",
    "status": "success"
  },
  "youtube": {
    "requested_at": "2025-06-19T10:30:00Z",
    "status": "pending"
  }
}
```

### Prices & Market Data

#### GET `/prices`
Fetch ADA price information.

**Response:**
```json
{
  "ada_usd": 1.25,
  "ada_eur": 1.15,
  "ada_gbp": 0.98,
  "market_cap": "45000000000",
  "volume_24h": "1200000000",
  "change_24h": 2.5
}
```

#### GET `/coingecko/price`
Fetch price data from CoinGecko (cached).

**Response:**
```json
{
  "cardano": {
    "usd": 1.25,
    "eur": 1.15,
    "market_cap_usd": 45000000000
  }
}
```

### Content Analysis

#### GET `/content-keywords`
Fetch trending keywords across content.

**Query Parameters:**
- `limit` (number, default: 20)

**Response:**
```json
[
  {
    "keyword": "Cardano",
    "frequency": 450,
    "trend": "up"
  }
]
```

### Newsletter

#### POST `/newsletter/subscribe`
Subscribe email to newsletter.

**Request Body:**
```json
{
  "email": "user@example.com",
  "language": "en"
}
```

**Response:**
```json
{
  "status": "subscribed",
  "email": "user@example.com"
}
```

## Error Responses

### 400 Bad Request
```json
{
  "error": "Invalid query parameters"
}
```

### 401 Unauthorized
```json
{
  "error": "API key required"
}
```

### 404 Not Found
```json
{
  "error": "Resource not found"
}
```

### 429 Too Many Requests
```json
{
  "error": "Too many requests. Please try again later."
}
```

### 500 Internal Server Error
```json
{
  "error": "Internal server error"
}
```

## Rate Limiting

- Admin/auth routes: 30 requests per minute per IP
- Public content routes: No rate limiting

## Caching

Most endpoints implement server-side caching:
- Articles/Videos: 1-5 minutes
- Settings/Languages: 1 hour
- Statistics: 10 minutes

## Examples

### Fetch latest Cardano news in Portuguese
```bash
curl "https://cardanofeed.com/api/articles?lang=pt&limit=10"
```

### Get combined timeline feed
```bash
curl "https://cardanofeed.com/api/timeline?limit=50&lang=en"
```

### Subscribe to newsletter
```bash
curl -X POST https://cardanofeed.com/api/newsletter/subscribe \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","language":"en"}'
```

### Fetch article as Markdown
```bash
curl "https://cardanofeed.com/api/articles/cardano-news-123abc/markdown"
```

## Webhooks & Real-time

Currently not supported. Check back later for WebSocket support.

## Terms of Use

- Respect rate limits
- Cache responses when possible
- Link back to Cardano Feed when using data
- Don't scrape without permission
- No automated mass downloads

## Support

For API issues or questions:
- Create an issue on GitHub
- Email: api@cardanofeed.com

---

**Last Updated:** 2025-06-19  
**API Version:** 1.0
