Posts API

Bu sayfa yazılarla ilgili her şeyi kapsıyor: liste çekmek, tek bir yazıyı okumak, yeni yazı oluşturmak, güncellemek, silmek. n8n'den taslak fırlatıyorsanız, mobil uygulamanız akışı çekiyorsa ya da dışarıdan içerik gönderiyorsanız — işiniz burada.

Tüm uç noktalar /api/v1/posts altında. Her istekte Authorization: Bearer ... header'ı gönderiyorsunuz ve token'ınızın ilgili posts:* kapsamına sahip olması gerekiyor.

Yazıları listele

GET /api/v1/posts

Kapsam: posts:read.

Elinize aldığınızda filtreleyebileceğiniz şeyler:

  • statusdraft, scheduled, published (varsayılan), archived
  • category — slug veya ID
  • author — kullanıcı ID'si
  • search — başlık ve içerikte kelime araması
  • page — sayfa numarası (1'den başlar)
  • per_page — sayfa başına öğe, en fazla 100 (varsayılan 20)
  • order_bypublished_at, updated_at, title
  • orderasc veya desc

Denemek için:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  "https://yoursite.com/api/v1/posts?status=published&category=nutrition&per_page=50"

Cevap iki anahtarlı bir JSON döner — data (yazı dizisi) ve pagination (sayfa bilgisi). Her yazı bu alanları içerir: id, title, slug, status, excerpt, content_html, content_markdown, author nesnesi, categories dizisi, tags, featured_image nesnesi (url + genişlik + yükseklik), published_at, updated_at ve son izleyicinin paylaşacağı hazır url.

{
    "data": [
        {
            "id": 123,
            "title": "10 high-protein breakfasts",
            "slug": "high-protein-breakfasts",
            "status": "published",
            "excerpt": "Start your day with...",
            "content_html": "<p>...</p>",
            "author": { "id": 1, "name": "Ada Lovelace" },
            "categories": [ { "id": 3, "slug": "nutrition", "name": "Nutrition" } ],
            "tags": [ "protein", "breakfast" ],
            "featured_image": { "id": 45, "url": "https://.../cover.jpg", "width": 1600, "height": 900 },
            "published_at": "2026-04-10T09:00:00Z",
            "url": "https://yoursite.com/blog/high-protein-breakfasts"
        }
    ],
    "pagination": { "page": 1, "per_page": 50, "total": 237, "total_pages": 5 }
}

Tek bir yazıyı getir

GET /api/v1/posts/{id}

Hem sayısal ID hem de slug kabul eder, ne elinizdeyse yollayın:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://yoursite.com/api/v1/posts/high-protein-breakfasts

Liste öğesiyle aynı şekli dönen tek farkı content_html ve content_markdown alanlarının burada tam içerikle dolu gelmesi.

Yazı oluştur

POST /api/v1/posts
Content-Type: application/json

Kapsam: posts:write. En azından title ve içerik (content_markdown veya content_html) göndermeniz gerekir; geri kalan her şey opsiyonel:

{
    "title": "My new post",
    "content_markdown": "# Hello\n\nThis is the body...",
    "status": "draft",
    "categories": [ "nutrition" ],
    "tags": [ "protein", "breakfast" ],
    "featured_image_id": 45,
    "seo": {
        "title": "Optional SEO title",
        "description": "Optional SEO description"
    }
}

status üç değerden biri olabilir: draft, scheduled, published. scheduled seçerseniz ileri tarihli bir published_at de göndermeniz lazım — yoksa sunucu hangi zamanda yayınlanacağını bilemez.

Başarılı olursa 201 Created ve GET ile aynı şekle sahip tam yazı nesnesi döner. id, slug, render edilmiş content_html ve url sunucu tarafında doldurulur.

Yazı güncelle

PUT /api/v1/posts/{id}

Kısmi güncelleme çalışıyor — yalnızca değiştirmek istediğiniz alanları gönderin, diğerleri olduğu gibi kalır. Bir taslağı yayına almak bu kadar basit:

{ "status": "published" }

Başarıda 200 OK ve güncel yazı gelir.

Yazı sil

DELETE /api/v1/posts/{id}

Varsayılanda soft delete yapar — yazının status'u archived olur, herkese açık görünümden kaybolur ama DB'de durur. Gerçekten kalıcı silmek istiyorsanız URL'ye ?hard=true ekleyin (bu DB satırını siler; medya ve yorumlar dokunulmaz).

Başarıda 204 No Content — gövde yoktur.

Hata kodları

| Kod | Ne demek | |------|---------| | 400 | İstek gövdesi geçersiz (eksik alan, yanlış tip) | | 401 | Token yok, geçersiz veya süresi dolmuş | | 403 | Token'ın bu kapsamı yok ya da IP kısıtlı | | 404 | Böyle bir yazı yok | | 409 | Slug çakışması (sunucu genelde kendi çözer) | | 422 | Doğrulama hatası — fields içinde tek tek hangi alanın sorunlu olduğunu görürsünüz | | 429 | Hız sınırını aştınız — Retry-After header'ına bakıp o kadar bekleyin | | 500 | Bizde bir şey koptu — X-Request-Id header'ını destek birimine iletin |

Hata gövdesi şöyle görünür:

{
    "error": "validation_failed",
    "message": "one or more fields are invalid",
    "fields": {
        "title": "required",
        "status": "must be one of: draft, scheduled, published"
    }
}

Pratik örnek: n8n'den taslak oluştur

Tipik bir senaryo — bir yerden (Google Form, Airtable, Slack komutu) { title, content } geliyor, bunu taslak olarak jekcms'e atmak istiyorsunuz:

  1. Webhook node — POST, path /new-draft
  2. HTTP Request node — Method POST, URL https://yoursite.com/api/v1/posts, Header Auth ile Authorization: Bearer {{$credentials.jekcmsToken}}, gövde:
{
    "title": "={{ $json.title }}",
    "content_markdown": "={{ $json.content }}",
    "status": "draft",
    "categories": ["auto-import"],
    "tags": ["from-webhook"]
}
  1. Respond to Webhook — çağıran kişi taslak URL'sini hemen görsün diye {{ $node["HTTP Request"].json.url }} döndürün.

HTTP Request node'unda Retry on fail seçeneğini açmayı unutmayın (3 deneme, üstel geri çekilme). Geçici ağ hıçkırıkları gönderileri düşürmesin.

Yeniliklerden ilk sen haberdar ol

Yeni özellikler, sürüm notları ve CMS rehberleri — ayda birkaç e-posta, spam yok.