Articles REST API

Version 1.0 • Base URL: /api/v1

Overview

The Articles REST API provides access to themed devotional and study material content in both English and Amharic languages.

Key Features

  • Versioned API - All endpoints under /api/v1/
  • Bilingual Content - English (en) and Amharic (am)
  • Rich Media - Cover images, square graphics, story graphics
  • Caching - 1 hour cache on all responses
  • CORS Enabled - Cross-origin requests supported

Endpoints

1. Get All Themes

Retrieve all published themes with subtopics and graphics.

GET /api/v1/articles

Response Example

[
  {
    "slug": "love-faith-and-hope",
    "title": {
      "en": "Love Faith Hope",
      "am": "ፍቅር እምነት ተስፋ"
    },
    "subtopics_count": 3,
    "subtopics": [
      {
        "title": {
          "en": "Love",
          "am": "ፍቅር"
        },
        "description": {
          "en": "A collection of beautiful and heart warming graphics",
          "am": "የሚያምር እና የልብ ሞቅ ምስሎች ስብስብ"
        },
        "covers": {
          "en": "https://res.cloudinary.com/.../cover_en.png",
          "am": "https://res.cloudinary.com/.../cover_am.png"
        },
        "images": {
          "square": {
            "en": ["https://res.cloudinary.com/.../square1.png"],
            "am": ["https://res.cloudinary.com/.../square1_am.png"]
          },
          "story": {
            "en": ["https://res.cloudinary.com/.../story1.png"],
            "am": ["https://res.cloudinary.com/.../story1_am.png"]
          }
        },
        "articles": {
          "devotional": {
            "en": "/api/v1/articles/love-faith-and-hope/love/devotional_en",
            "am": "/api/v1/articles/love-faith-and-hope/love/devotional_am"
          },
          "study_material": {
            "en": "/api/v1/articles/love-faith-and-hope/love/study_material_en",
            "am": "/api/v1/articles/love-faith-and-hope/love/study_material_am"
          }
        },
        "artists": [
          {
            "name": "John Doe",
            "role": "Graphic Designer",
            "bio": "Creative designer with passion for visual storytelling"
          },
          {
            "name": "Jane Smith",
            "role": "Illustrator",
            "bio": "Digital artist specializing in religious artwork"
          }
        ]
      }
    ]
  }
]

2. Get Single Theme

Retrieve details for a specific theme.

GET /api/v1/articles/{theme}

Parameters

ParameterTypeDescription
themestringTheme slug (e.g., love-faith-and-hope)

Response Example

{
  "slug": "love-faith-and-hope",
  "title": {
    "en": "Love Faith Hope",
    "am": "ፍቅር እምነት ተስፋ"
  },
  "subtopics": [
    {
      "title": { "en": "Love", "am": "ፍቅር" },
      "description": { "en": "...", "am": "..." },
      "covers": { "en": "https://...", "am": "https://..." },
      "images": {
        "square": { "en": ["https://..."], "am": ["https://..."] },
        "story": { "en": ["https://..."], "am": ["https://..."] }
      },
      "articles": {
        "devotional": { "en": "/api/v1/...", "am": "/api/v1/..." },
        "study_material": { "en": "/api/v1/...", "am": null }
      },
      "artists": [
        { "name": "Artist Name", "role": "Designer", "bio": "..." }
      ]
    }
  ]
}

3. Get Single Subtopic

Retrieve details for a specific subtopic with authors and content availability.

GET /api/v1/articles/{theme}/{subtopic}

Parameters

ParameterTypeDescription
themestringTheme slug
subtopicstringSubtopic slug (e.g., love)

Response Example

{
  "theme_en": "Love Faith Hope",
  "theme_slug": "love-faith-and-hope",
  "title": { "en": "Love", "am": "ፍቅር" },
  "slug": "love",
  "description": { "en": "...", "am": "..." },
  "covers": {
    "en": "https://res.cloudinary.com/.../cover_en.png",
    "am": "https://res.cloudinary.com/.../cover_am.png"
  },
  "images": {
    "square": {
      "en": ["https://res.cloudinary.com/.../square1.png"],
      "am": ["https://res.cloudinary.com/.../square1_am.png"]
    },
    "story": {
      "en": ["https://res.cloudinary.com/.../story1.png"],
      "am": ["https://res.cloudinary.com/.../story1_am.png"]
    }
  },
  "available_content": {
    "devotional": { "en": true, "am": true },
    "study_material": { "en": true, "am": false }
  },
  "authors": {
    "devotional_en": [
      { "name": "John Doe", "role": "Writer", "bio": "Devotional author" }
    ],
    "devotional_am": [
      { "name": "አበበ በቀለ", "role": "ጸሃፊ", "bio": "የምሥጢር ጸሃፊ" }
    ],
    "study_material_en": [
      { "name": "Jane Smith", "role": "Theologian", "bio": "Biblical scholar" }
    ],
    "study_material_am": []
  },
  "artists": [
    { "name": "Artist Name", "role": "Designer", "bio": "Visual artist" }
  ]
}

4. Get Single Article

Retrieve the full content of a specific article with cleaned markdown.

GET /api/v1/articles/{theme}/{subtopic}/{slug}

Parameters

ParameterTypeDescription
themestringTheme slug
subtopicstringSubtopic slug
slugstringFormat: {type}_{lang}
(e.g., devotional_en, study_material_am)

Slug Format

  • Types: devotional, study_material
  • Languages: en (English), am (Amharic)

Response Example

{
  "theme": "love-faith-and-hope",
  "subtopic": "love",
  "type": "devotional",
  "lang": "en",
  "title": "True Love",
  "date": "December 30, 2025",
  "audio": "youtube/_cMxraX_5RE",
  "header": "Lost in Doubts? God's Love Never Quits on You",
  "graphics": {
    "covers": {
      "en": "https://res.cloudinary.com/.../cover_en.png",
      "am": "https://res.cloudinary.com/.../cover_am.png"
    },
    "images": {
      "square": {
        "en": ["https://res.cloudinary.com/.../square1.png"],
        "am": ["https://res.cloudinary.com/.../square1_am.png"]
      },
      "story": {
        "en": ["https://res.cloudinary.com/.../story1.png"],
        "am": ["https://res.cloudinary.com/.../story1_am.png"]
      }
    }
  },
  "content": "Ever catch yourself wondering if God's love is really unconditional?\n\nIn Romans 8:38-39, Paul writes: \"For I am convinced that neither death nor life, neither angels nor demons, neither the present nor the future, nor any powers, neither height nor depth, nor anything else in all creation, will be able to separate us from the love of God that is in Christ Jesus our Lord.\"\n\nThis passage reminds us that God's love isn't based on our performance. It's not something we can earn or lose. It's a gift that remains constant through every season of life."
}
Note: The content field contains cleaned markdown with all HTML/Svelte components removed.

Error Handling

HTTP Status Codes

CodeDescription
200Success
400Bad Request - Invalid parameters
404Not Found - Resource does not exist
500Internal Server Error

Error Response Format

{
  "error": "Error message describing what went wrong"
}

Common Errors

// 404 - Theme not found
{
  "error": "Theme not found"
}

// 400 - Invalid slug format
{
  "error": "Invalid slug format. Expected format: {type}_{lang} (e.g., devotional_en, study_material_am)"
}

// 400 - Invalid language
{
  "error": "Invalid language. Must be \"en\" or \"am\""
}

Code Examples

JavaScript / Fetch API

// Get all themes
const response = await fetch('/api/v1/articles');
const themes = await response.json();

// Get specific article
const article = await fetch(
  '/api/v1/articles/love-faith-and-hope/love/devotional_en'
);
const data = await article.json();

console.log(data.title);    // "True Love"
console.log(data.content);  // Markdown content

React / React Native

function Article({ theme, subtopic, slug }) {
  const [article, setArticle] = useState(null);
  
  useEffect(() => {
    fetch(`/api/v1/articles/${theme}/${subtopic}/${slug}`)
      .then(res => res.json())
      .then(setArticle);
  }, [theme, subtopic, slug]);
  
  if (!article) return <Loading />;
  
  return (
    <View>
      <Image source={{ uri: article.graphics.covers.en }} />
      <Text>{article.title}</Text>
      <Markdown>{article.content}</Markdown>
    </View>
  );
}

Error Handling

async function getArticle(theme, subtopic, slug) {
  try {
    const response = await fetch(
      `/api/v1/articles/${theme}/${subtopic}/${slug}`
    );
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error);
    }
    
    return await response.json();
  } catch (error) {
    console.error('Failed to fetch article:', error.message);
    return null;
  }
}