Skip to content

Your First API Call

Learn how to make your first authenticated API call to Corgi and receive personalized recommendations. This guide demonstrates the core value of the service: intelligent, privacy-first content discovery.

Prerequisites

Before making your first API call, you need:

  1. Running Corgi instance - Complete the 5-Minute Integration guide first
  2. Mastodon access token - Your personal access token from your Mastodon instance
  3. Mastodon instance URL - The domain of your Mastodon server (e.g., mastodon.social)

Getting Your Access Token

To get your Mastodon access token, go to your Mastodon instance → Settings → Development → New Application. Create an app with read permissions and copy the access token.

Authentication Requirements

Corgi requires two headers for authenticated requests:

  1. Authorization header - Your Mastodon Bearer token
  2. X-Mastodon-Instance header - Your Mastodon instance domain

Instance Header Purpose

The X-Mastodon-Instance header tells Corgi which Mastodon server to fetch content from and helps personalize recommendations based on your instance's community.

Making Your First Call

Quick Test with curl

Test the recommendations endpoint with a simple curl command:

Terminal
curl -X GET "http://localhost:5002/api/v1/recommendations" \
  -H "Authorization: Bearer YOUR_MASTODON_TOKEN" \
  -H "X-Mastodon-Instance: mastodon.social" \
  -H "Content-Type: application/json" \
  --get \
  --data-urlencode "user_id=demo_user" \
  --data-urlencode "limit=5"

Replace the Values

  • Replace YOUR_MASTODON_TOKEN with your actual access token
  • Replace mastodon.social with your Mastodon instance
  • Replace demo_user with a unique identifier for your user

Python Example

For a more practical integration, use Python's requests library:

recommendations_example.py
import requests
import json

# Configuration
CORGI_API_BASE = "http://localhost:5002"
MASTODON_TOKEN = "YOUR_MASTODON_TOKEN"
MASTODON_INSTANCE = "mastodon.social"
USER_ID = "demo_user"

def get_recommendations(user_id, limit=10):
    """Get personalized recommendations for a user."""

    headers = {
        "Authorization": f"Bearer {MASTODON_TOKEN}",
        "X-Mastodon-Instance": MASTODON_INSTANCE,
        "Content-Type": "application/json"
    }

    params = {
        "user_id": user_id,
        "limit": limit
    }

    try:
        response = requests.get(
            f"{CORGI_API_BASE}/api/v1/recommendations",
            headers=headers,
            params=params
        )

        if response.status_code == 200:
            return response.json()
        else:
            print(f"Error: {response.status_code} - {response.text}")
            return None

    except requests.exceptions.RequestException as e:
        print(f"Request failed: {e}")
        return None

# Get recommendations
recommendations = get_recommendations(USER_ID, limit=5)

if recommendations:
    print(f"Got {len(recommendations)} recommendations:")
    for post in recommendations:
        print(f"- {post.get('account', {}).get('display_name', 'Unknown')}: {post.get('content', '')[:100]}...")
        if post.get('recommendation_reason'):
            print(f"  Reason: {post['recommendation_reason']}")
else:
    print("No recommendations received")

JavaScript/Node.js Example

recommendations_example.js
const axios = require('axios');

const CORGI_API_BASE = 'http://localhost:5002';
const MASTODON_TOKEN = 'YOUR_MASTODON_TOKEN';
const MASTODON_INSTANCE = 'mastodon.social';
const USER_ID = 'demo_user';

async function getRecommendations(userId, limit = 10) {
    try {
        const response = await axios.get(`${CORGI_API_BASE}/api/v1/recommendations`, {
            headers: {
                'Authorization': `Bearer ${MASTODON_TOKEN}`,
                'X-Mastodon-Instance': MASTODON_INSTANCE,
                'Content-Type': 'application/json'
            },
            params: {
                user_id: userId,
                limit: limit
            }
        });

        return response.data;
    } catch (error) {
        console.error('Error fetching recommendations:', error.response?.data || error.message);
        return null;
    }
}

// Get and display recommendations
getRecommendations(USER_ID, 5).then(recommendations => {
    if (recommendations) {
        console.log(`Got ${recommendations.length} recommendations:`);
        recommendations.forEach(post => {
            console.log(`- ${post.account?.display_name || 'Unknown'}: ${post.content?.substring(0, 100)}...`);
            if (post.recommendation_reason) {
                console.log(`  Reason: ${post.recommendation_reason}`);
            }
        });
    } else {
        console.log('No recommendations received');
    }
});

Understanding the Response

Successful Response

A successful API call returns a JSON array of recommended posts:

[
  {
    "id": "109876543211234567",
    "content": "<p>Just discovered this amazing new privacy tool! 🔒</p>",
    "account": {
      "id": "123456",
      "username": "privacyadvocate",
      "display_name": "Privacy Advocate",
      "avatar": "https://files.mastodon.social/accounts/avatars/..."
    },
    "created_at": "2025-01-15T10:30:00.000Z",
    "ranking_score": 0.87,
    "recommendation_reason": "Popular in your network",
    "favourites_count": 42,
    "reblogs_count": 18,
    "replies_count": 7,
    "favourited": false,
    "reblogged": false
  }
]

Key Response Fields

  • id - Unique post identifier
  • content - Post content (HTML format)
  • account - Author information
  • ranking_score - Recommendation confidence (0.0 to 1.0)
  • recommendation_reason - Why this post was recommended
  • favourited / reblogged - Your interaction status with this post

Recommendation Score

Higher ranking_score values (closer to 1.0) indicate stronger confidence in the recommendation. Scores above 0.8 are typically very relevant to your interests.

API Parameters

Required Parameters

  • user_id (string) - Unique identifier for the user

Optional Parameters

  • limit (integer, default: 20, max: 40) - Number of recommendations to return
  • exclude_ids (string) - Comma-separated list of post IDs to exclude
  • max_id (string) - Return results older than this ID (pagination)
  • since_id (string) - Return results newer than this ID (pagination)

Error Handling

Common Error Responses

401 Unauthorized

{
  "error": "Authentication required",
  "message": "Please provide valid API key or Bearer token"
}

400 Bad Request

{
  "error": "Invalid request",
  "message": "Missing required parameter: user_id"
}

Troubleshooting

No recommendations returned: - Verify your user_id is correct - Check that your Mastodon token has read permissions - Ensure the X-Mastodon-Instance header matches your actual instance

Authentication errors: - Double-check your Bearer token format - Verify the token is still valid on your Mastodon instance - Ensure there are no extra spaces in the Authorization header

Next Steps

You've Made Your First Call!

Congratulations! You've successfully retrieved personalized recommendations from Corgi. You now have the foundation for building intelligent, privacy-first recommendation features.

What's Next?

  • Integrate with your app - Use the examples above as a starting point
  • Explore advanced features - Learn about the ELK Integration for seamless Mastodon client integration
  • Understand the architecture - Dive deeper into how recommendations work in Architecture Deep Dive

Advanced Usage

Get recommendations with pagination
curl -X GET "http://localhost:5002/api/v1/recommendations?user_id=demo_user&limit=10&max_id=109876543211234567" \
  -H "Authorization: Bearer YOUR_MASTODON_TOKEN" \
  -H "X-Mastodon-Instance: mastodon.social"
Exclude specific posts
curl -X GET "http://localhost:5002/api/v1/recommendations?user_id=demo_user&exclude_ids=12345,67890" \
  -H "Authorization: Bearer YOUR_MASTODON_TOKEN" \
  -H "X-Mastodon-Instance: mastodon.social"

You now have the power of intelligent recommendations at your fingertips! The Corgi API provides the foundation for building sophisticated, privacy-respecting recommendation systems for the Fediverse.