Developer documentation
We're developers at heart, and as such we wanted to make it as easy as possible to build on top of Owl. Whether you want to create cards programmatically, build a whole new interface for the app, or — hint, hint — use MCP to integrate Owl with your favorite large language model, follow the steps below to get started.
We just open-sourced the Owl MCP server. Integrate Owl with your favorite LLMs via Claude Desktop, Cursor, etc. Download the source code on GitHub.
API reference
Getting an API Key
To obtain an API key, log in to your Owl account and navigate to your profile settings. From there, you can create a new API key with a custom name.
Owl API Base URL
All API requests should be made to https://api.owl.cards
Using Your API Key
Include your key in the X-Api-Key
header with requests to api.owl.cards
:
curl -X GET "https://api.owl.cards/decks" \ -H "X-Api-Key: your_api_key_here" \ -H "Content-Type: application/json"
Security
Get All Decks
Returns a paginated list of the user's decks.
GET /decks
Query Parameters
page
- Page number (default: 1)per_page
- Items per page (default: 20)sort
- Sort field (e.g. "-created_at" for descending)
Response
{ "items": [ { "id": "string", "title": "string", "description": "string", "created_at": "string", "updated_at": "string", "archived_at": "string | null", "user_id": "string", "public": boolean, "cards_count": number, "cards_in_review_count": number, "completion_percentage": number } ], "pagination": { "current_page": number, "per_page": number, "total_pages": number, "total_count": number } }
Get a Specific Deck
Returns details for a specific deck.
GET /decks/{deck_id}
Response
{ "id": "string", "title": "string", "description": "string", "created_at": "string", "updated_at": "string", "archived_at": "string | null", "user_id": "string", "public": boolean, "cards_count": number, "cards_in_review_count": number, "completion_percentage": number }
Get Deck with Cards
Returns a deck with all its cards included.
GET /decks/{deck_id}?include=cards
Response
{ "id": "string", "title": "string", "description": "string", "created_at": "string", "updated_at": "string", "archived_at": "string | null", "user_id": "string", "public": boolean, "cards_count": number, "cards_in_review_count": number, "completion_percentage": number, "cards": [ { "id": "string", "type": "BasicCard" | "ClozeCard", "front": "string", // for BasicCard "back": "string", // for BasicCard "text": "string", // for ClozeCard "created_at": "string", "updated_at": "string", "archived_at": "string | null", "stability": number, "difficulty": number, "reps": number, "lapses": number, "state": "new" | "learning" | "review" | "relearning", "last_reviewed_at": "string | null", "next_review_at": "string | null", "url": "string", "deck_id": "string", "deck_title": "string" } ] }
Create a Deck
Creates a new deck with the provided details.
POST /decks
Request Body
{ "title": "string", "description": "string", "public": boolean, // optional, default: false "cards": [ // optional { "type": "BasicCard", "front": "string", "back": "string" }, { "type": "ClozeCard", "text": "string" } ] }
Response
{ "id": "string", "title": "string", "description": "string", "created_at": "string", "updated_at": "string", "archived_at": "string | null", "user_id": "string", "public": boolean, "cards_count": number, "cards_in_review_count": number, "completion_percentage": number }
Update a Deck
Updates an existing deck with the provided changes.
PATCH /decks/{deck_id}
Request Body
{ "title": "string", // optional "description": "string", // optional "public": boolean // optional }
Response
{ "id": "string", "title": "string", "description": "string", "created_at": "string", "updated_at": "string", "archived_at": "string | null", "user_id": "string", "public": boolean, "cards_count": number, "cards_in_review_count": number, "completion_percentage": number }
Archive a Deck
Archives a deck without deleting it.
POST /decks/{deck_id}/archive
Unarchive a Deck
Restores an archived deck.
POST /decks/{deck_id}/unarchive
Delete a Deck
Permanently deletes a deck and all its cards.
DELETE /decks/{deck_id}
Export a Deck
Exports a deck in a format suitable for importing into other systems.
GET /decks/{deck_id}/export
Code examples
// Example: Creating a new deck and adding cards const API_KEY = 'your_api_key_here'; const BASE_URL = 'https://api.owl.cards'; // Create a new deck async function createDeck(title, description) { const response = await fetch(`${BASE_URL}/decks`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': API_KEY }, body: JSON.stringify({ title, description }) }); return await response.json(); } // Add a card to a deck async function addCard(deckId, front, back) { const response = await fetch(`${BASE_URL}/decks/${deckId}/cards`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': API_KEY }, body: JSON.stringify({ deck_id: deckId, type: 'basic', front, back }) }); return await response.json(); } // Example usage async function main() { try { // Create a new deck const deck = await createDeck('My Study Deck', 'A deck for studying'); console.log('Created deck:', deck); // Add a card to the deck const card = await addCard(deck.id, 'What is the capital of France?', 'Paris'); console.log('Added card:', card); } catch (error) { console.error('Error:', error); } } main();