İçeriğe atla

Geliştirici kılavuzu

Kendi içerik akışınızdan Amaposta'ya gönderi gönderin: medya yükleyin, her kanal için bir gönderi oluşturun, planlayın ve yayınlandığında haber alın.

Kimlik doğrulama

Panelde Ayarlar, API ve webhook'lar bölümünden bir API anahtarı oluşturun. Anahtarlar ss_live_ ile başlar, tek bir çalışma alanına aittir ve belirli projelerle sınırlanabilir. Anahtarı her istekte bearer belirteci olarak gönderin:

Anahtarı kontrol et
curl https://www.amaposta.com/api/v1/me \
  -H "Authorization: Bearer ss_live_…"

Yanıt anahtarı, yetki kapsamlarını ve çalışma alanını belirtir. Her anahtarın bir veya daha fazla yetki kapsamı vardır:

Yetki kapsamıİzin verir
content:readProjeleri, kanalları, gönderileri ve medyayı okuyun.
content:writeMedya yükleyin, gönderi oluşturun veya düzenleyin.
posts:publishİnceleme olmadan planlayın ve yayınlayın. Bu izin olmadan gönderiler, onay kullanan projelerde inceleme kutusuna gider; diğer projelerde taslak olarak kalır.

Her anahtar dakikada 120 istek yapabilir. Bu sınır aşılırsa rate_limited koduyla 429 alırsınız; biraz bekleyip yeniden deneyin.

Projeler ve kanallar

Gönderiler bir projede bulunur. Anahtarınızın görebildiği projeleri, ardından birinin kanallarını listeleyin. Bir kanalı hedeflemek veya metnini değiştirmek için kanalın kimliği gerekir.

Projeleri ve kanalları listeleyin
curl https://www.amaposta.com/api/v1/projects \
  -H "Authorization: Bearer $AMAPOSTA_KEY"

curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/channels \
  -H "Authorization: Bearer $AMAPOSTA_KEY"

Bir kanalın provider değeri (youtube, instagram, tiktok, x, facebook, custom veya sandbox), status değeri (active, expiring, needs_reconnect, error veya disabled) ve supports alanında desteklediği gönderi türleri bulunur.

Medya yükle

Görseller ve videolar proje başına bir kez yüklenir ve istediğiniz sayıda gönderide kullanılabilir. Yüklemenin üç yolu vardır.

Doğrudan yükleme

Dosyayı, file adlı alanda multipart form verisi olarak gönderin. Birkaç yüz MB'a kadar dosyalar için en uygun yöntemdir.

POST /api/v1/projects/{project_id}/media
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media \
  -H "Authorization: Bearer $AMAPOSTA_KEY" \
  -F "[email protected]"

Büyük dosyalar için önceden imzalanmış yükleme

Bir yükleme URL'si isteyin, baytları PUT ile doğrudan depolamaya yükleyin, ardından Amaposta'ya tamamlandığını bildirin.

Üç istek
# 1. Ask for an upload URL. The response is {"media": { … }, "upload_url": "…"}
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media/uploads \
  -H "Authorization: Bearer $AMAPOSTA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename": "batch-142.mp4", "content_type": "video/mp4", "size_bytes": 48213844}'

# 2. Upload the bytes to upload_url
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: video/mp4" \
  --upload-file batch-142.mp4

# 3. Finish the upload
curl -X POST https://www.amaposta.com/api/v1/media/$MEDIA_ID/complete \
  -H "Authorization: Bearer $AMAPOSTA_KEY"

Bir URL'den içe aktarın

Amaposta'ya herkese açık bir URL verin; dosyayı arka planda indirsin. Bu adımı atlayıp gönderiyi oluştururken media_url de iletebilirsiniz.

POST /api/v1/projects/{project_id}/media/import
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media/import \
  -H "Authorization: Bearer $AMAPOSTA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://cdn.example.com/batch-142.mp4"}'

Her yükleme bir medya nesnesi döndürür. Nesnenin status değeri pending'den processing'e, ardından ready'ye (veya bir error ile failed'a) geçer. İşlendikten sonra width, height, duration_ms ve bir küçük resim içerir. GET /api/v1/media/{id} uç noktasını düzenli sorgulayın veya media.ready webhook'unu dinleyin. Döndürülen url imzalıdır ve 12 saat geçerlidir.

Gönderi oluştur

POST /api/v1/projects/{project_id}/posts, her kanal için bir teslimatı olan tek bir gönderi oluşturur. Amaposta bunu platforma göre uyarlar: başlıklar yalnızca başlık alanı olan platformlara gider; hashtag'ler YouTube'da etikete, diğerlerinde metin içi hashtag'e dönüşür.

Video gönderisi oluşturup kuyruğa ekleyin
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/posts \
  -H "Authorization: Bearer $AMAPOSTA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: episode-142" \
  -d @- <<'JSON'
{
  "kind": "video",
  "title": "How we roast a batch in 12 minutes",
  "description": "From green beans to first crack. We filmed one batch start to finish.",
  "hashtags": ["coffee", "behindthescenes"],
  "media_url": "https://cdn.example.com/batch-142.mp4",
  "cover_url": "https://cdn.example.com/batch-142-cover.jpg",
  "overrides": {
    "<x-channel-id>": {
      "description": "Batch 142 is out: green beans to first crack in 12 minutes."
    },
    "<youtube-channel-id>": {
      "options": { "privacy": "unlisted" }
    }
  },
  "schedule": { "mode": "queue" },
  "external_ref": "episode-142",
  "metadata": {
    "pipeline": { "name": "nightly-cut", "run": "2026-10-17" }
  }
}
JSON

Alanlar

AlanNe yapar?
kindtext, image veya video. Zorunludur.
titleBaşlık alanı olan platformlar kullanır: YouTube, TikTok fotoğraf gönderileri, Facebook videoları.
descriptionAçıklama veya gönderi metni. body, caption ya da text olarak da kabul edilir.
hashtags# içeren veya içermeyen bir liste.
media_id, media_urlYüklenmiş bir medya kimliği veya Amaposta'nın sizin için indireceği herkese açık bir URL. Görsel ve video gönderileri için gereklidir.
cover_media_id, cover_urlPlatformun desteklediği durumlarda videolar için kapak görseli.
channelsPaylaşım yapılacak kanal kimlikleri. Bu gönderi türünü destekleyen, projedeki tüm etkin kanalları kullanmak için bu alanı göndermeyin.
overridesKanal kimliğine göre kanala özel değişiklikler: title, description, hashtags ve YouTube'un privacy alanı gibi platform options değerleri.
schedulemode, at (ISO 8601 biçiminde bir at ile), now veya bir sonraki boş paylaşım zamanı için queue olabilir. Taslak oluşturmak için bu alanı göndermeyin.
external_refGönderide ve Özel API teslimatlarında aynen geri döndürülen kendi referansınız.
metadataGönderiyle birlikte saklanan serbest biçimli JSON. Üretilen içeriği işaretlemek için "pipeline" ekleyin; panelde gösterilir ve webhook'lar kaynağı pipeline olarak bildirir.

Yanıt, her kanal için deliveries içinde bir kayıt dahil, gönderinin kendisidir.

Güvenli yeniden denemeler

Ağlarda istekler kaybolabilir. Gönderi oluştururken bir Idempotency-Key başlığı gönderin; aynı anahtarla yeniden deneme, ikinci bir gönderi oluşturmak yerine ilk denemedeki gönderiyi döndürür. Kendi tarafınızda sabit bir değer kullanın; örneğin iş veya bölüm kimliği. Anahtarlar 200 karaktere kısaltılır.

Planla ve yayınla

POST /api/v1/posts/{post_id}/schedule ile bir taslağı planlayın, hemen yayınlayın, kuyruğa ekleyin veya takvimden kaldırın.

Bir zamana planla
curl https://www.amaposta.com/api/v1/posts/$POST_ID/schedule \
  -H "Authorization: Bearer $AMAPOSTA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mode": "at", "at": "2026-10-20T07:00:00Z"}'
  • atBelirtilen zamanda, iki yıl sonrasına kadar yayınlar.
  • nowHemen yayınlar.
  • queueÖnümüzdeki 12 hafta içinde gönderinin kanalları için bir sonraki boş paylaşım zamanını alır.
  • unscheduleGönderiyi yeniden taslaklara taşır.

Herhangi bir gönderi planlanmadan önce düzenleyicidekiyle aynı kontroller çalışır. Bir kontrol başarısız olursa istek, Planlamadan önce bunu düzeltin: YouTube için başlık gerekiyor. gibi bir mesajla 400 döndürür. Planlama için posts:publish yetkisi veya onayların açık olduğu bir proje gerekir; ikinci durumda gönderi inceleme kutusunda bekler.

Gönderileri ve teslimatları okuyun

Bir projenin gönderilerini status (virgülle ayrılmış durumlar veya inbox, queue ya da history), from/to aralığı, limit ve offset ile filtreleyerek listeleyin. Yanıt {"items": […], "total": n} biçimindedir.

Yaklaşanlar ve bir gönderinin ayrıntıları
curl "https://www.amaposta.com/api/v1/projects/$PROJECT_ID/posts?status=queue" \
  -H "Authorization: Bearer $AMAPOSTA_KEY"

curl https://www.amaposta.com/api/v1/posts/$POST_ID \
  -H "Authorization: Bearer $AMAPOSTA_KEY"

Bir gönderinin genel bir status değeri (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial veya failed) ve her kanal için bir teslimatı vardır:

deliveries[]
"deliveries": [
  {
    "id": "0192b7d4-…",
    "channel_id": "0192b7a1-…",
    "status": "published",
    "url": "https://www.youtube.com/watch?v=…",
    "error": null,
    "published_at": "2026-10-20T07:00:41Z"
  },
  {
    "id": "0192b7d4-…",
    "channel_id": "0192b7a9-…",
    "status": "failed",
    "url": null,
    "error": {
      "code": "endpoint_unavailable",
      "message": "Your endpoint returned 503 Service Unavailable",
      "hint": "Amaposta will retry with backoff."
    },
    "published_at": null
  }
]

Teslimat durumları pending, scheduled, publishing, processing, published, failed ve cancelled değerleridir. DELETE /api/v1/posts/{post_id} bir gönderiyi kaldırır.

Hatalar

Her hata aynı yapıdadır: sabit bir code, kullanıcılara gösterebileceğiniz bir message ve bazen fields (alan bazında mesajlar) ile bir hint içeren error nesnesi.

422 Unprocessable Entity
{
  "error": {
    "code": "validation",
    "message": "Please fix the highlighted fields.",
    "fields": {
      "kind": "Use text, image or video."
    }
  }
}
DurumKodAnlamı
400bad_requestİstek, talep edildiği şekilde gerçekleştirilemiyor; örneğin kontrolleri geçemeyen bir gönderiyi planlamak.
401unauthorizedAPI anahtarı eksik, yanlış veya iptal edilmiş.
402plan_limitÇalışma alanının planı buna izin vermiyor; hangi sınır olduğu limit alanında belirtilir.
403forbiddenAnahtarda bir yetki kapsamı veya projeye erişim eksik.
404not_foundBöyle bir proje, gönderi, medya veya uç nokta yok.
409conflictDeğişiklik mevcut durumla çakışıyor; örneğin zaten yayınlanmakta olan bir gönderiyi düzenlemek.
422validationBir veya daha fazla alan düzeltilmeli; fields alanına bakın.
429rate_limitedBu anahtarla dakikada 120'den fazla istek yapıldı.
502provider_errorBir platform reddetti veya başarısız oldu; ne yapılacağını hint belirtir.

Webhook'lar

Ayarlar, API ve webhook'lar bölümünde bir uç nokta ekleyin, istediğiniz olayları seçin ve imzalama sırrını kopyalayın. Amaposta her olay için URL'nize JSON içeren bir POST isteği gönderir. 2xx dışındaki yanıtlar veya 15 saniye içinde yanıt alınamaması durumunda istekler giderek uzayan aralıklarla yeniden denenir. Sürekli başarısız olan uç noktalar kapatılır ve yöneticilere bildirilir.

OlayGönderilme zamanı
post.createdBir gönderi oluşturuldu (panel veya API)
post.scheduledBir gönderi planlandı
post.approvedBir gönderi onaylandı
post.publishedBir gönderi bir kanalda yayına girdi
post.failedBir gönderi bir kanalda yayınlanamadı
channel.connectedBir kanal bağlandı veya yeniden bağlandı
channel.disconnectedBir kanalın bağlantısı kesildi
media.readyBir yüklemenin işlenmesi tamamlandı
media.failedBir yükleme işlenemedi
post.published
POST /your/webhook HTTP/1.1
Content-Type: application/json
User-Agent: Amaposta-Webhooks/1.0
X-Amaposta-Event: post.published
X-Amaposta-Event-Id: 0192b7e0-…
X-Amaposta-Signature: t=1792479641,v1=5f2b0c…

{
  "id": "0192b7e0-…",
  "type": "post.published",
  "created_at": "2026-10-20T07:00:41Z",
  "project_id": "0192a3f1-…",
  "data": {
    "post_id": "0192b7c8-…",
    "delivery_id": "0192b7d4-…",
    "channel_id": "0192b7a1-…",
    "provider": "youtube",
    "external_id": "…",
    "url": "https://www.youtube.com/watch?v=…"
  }
}

İmzayı doğrulayın

X-Amaposta-Signature değeri t=<unix seconds>,v1=<hex> biçimindedir. Buradaki v1, ham istek gövdesi üzerinden hesaplanan HMAC_SHA256(secret, t + "." + body) değeridir. Bunu kendiniz hesaplayın, sabit sürede karşılaştırın ve tekrar saldırılarını önlemek için eski zaman damgalarını reddedin.

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (string or Buffer).
export function verifySignature(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest();
  const given = Buffer.from(parts.v1 ?? "", "hex");
  return given.length === expected.length && crypto.timingSafeEqual(given, expected);
}
Python
import hashlib
import hmac
import time


def verify_signature(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if abs(time.time() - t) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Özel API kanalları

Bir Özel API kanalı, sizin çalıştırdığınız bir HTTPS uç noktasına yayın yapar: CMS'niz, bir bülten aracı veya Amaposta'nın henüz desteklemediği bir platform. Diğer kanallar gibi takvimde yer alır, kontrollerden ve onaydan geçer, yeniden denenir. Bir gönderi yayınlandığında Amaposta her teslimat için bir POST gönderir:

Uç noktanızın aldığı veriler
POST /amaposta/publish HTTP/1.1
Authorization: Bearer <your API key>
Content-Type: application/json
Idempotency-Key: 0192b7d4-…
X-Amaposta-Delivery: 0192b7d4-…
X-Amaposta-Signature: t=1792479600,v1=9ac41e…

{
  "id": "0192b7d4-…",
  "type": "post.publish",
  "created_at": "2026-10-20T07:00:00Z",
  "content": {
    "kind": "video",
    "title": "How we roast a batch in 12 minutes",
    "text": "From green beans to first crack. We filmed one batch start to finish.",
    "hashtags": ["coffee", "behindthescenes"],
    "media": {
      "url": "https://…",
      "content_type": "video/mp4",
      "size_bytes": 48213844,
      "width": 1080,
      "height": 1920,
      "duration_ms": 58000,
      "filename": "batch-142.mp4"
    },
    "cover": null,
    "options": {}
  },
  "post": {
    "id": "0192b7c8-…",
    "external_ref": "episode-142",
    "scheduled_at": "2026-10-20T07:00:00Z",
    "metadata": {
      "pipeline": { "name": "nightly-cut" }
    }
  },
  "project": { "id": "0192a3f1-…", "name": "Spring launch" },
  "channel": { "id": "0192b7a9-…", "name": "api.example.com" }
}

Nasıl yanıt verilir?

  • 2xxYayınlandı. İsteğe bağlı olarak {"id": "…", "url": "…"} döndürün; bağlantı gönderide görünür.
  • 401, 403Anahtar reddedildi. Kanal yeniden bağlanmak üzere işaretlenir ve yöneticilere haber verilir. Geçersiz imza için bu kodları kullanmayın.
  • 5xx, 408, 429Geçici. Amaposta giderek uzayan aralıklarla yeniden dener.
  • Diğer 4xxGönderi mesajınızla birlikte başarısız olarak işaretlenir; birisi sorunu giderip Yeniden dene'ye basabilir.
Express ile bir alıcı
app.post("/amaposta/publish", express.raw({ type: "application/json" }), async (req, res) => {
  const signature = req.get("X-Amaposta-Signature") ?? "";
  if (!verifySignature(req.body, signature, process.env.AMAPOSTA_SIGNING_SECRET)) {
    return res.status(400).json({ message: "Bad signature" });
  }
  const delivery = JSON.parse(req.body);
  const item = await publishToYourSystem(delivery.content, req.get("Idempotency-Key"));
  res.json({ id: item.id, url: item.url });
});

Uç noktanız internetten erişilebilir olmalıdır; yönlendirmeler izlenmez. Kanalı bağladığınızda Amaposta, ayarladıysanız sağlık URL'nize GET, aksi hâlde uç noktaya OPTIONS isteği göndererek kontrol eder.

Sandbox kanalları

Sandbox kanalı gerçek bir kanal gibi davranır, ancak Amaposta dışına hiçbir şey çıkmaz. Entegrasyonunuzu uçtan uca geliştirmek ve test etmek için kullanın: gönderiler planlanır, yayına girer, yayınlanır veya başarısız olur ve aynı webhook'ları tetikler. Sandbox kanalları her planda ücretsizdir ve kanal sınırına dahil edilmez.

Eklediğinizde nasıl davranacağını seçin:

  • Her zaman başarılı olHer gönderi yayınlanır.
  • Ara sıra başarısız olGerçek bir kesintiyi beklemeden hataları ve yeniden denemeleri görün.
  • Her zaman başarısız olpost.failed işleme mantığınızı test edin.
  • Süresi dolmuş bağlantıErişim süresi dolduğunda yeniden bağlanma uyarılarının ve bağlantılarının nasıl göründüğünü görün.

Platform kuralları

Her kanal türünün kabul ettiği içerikler. Kontroller aynı sınırları kullanır; böylece çoğu sorun yayın sırasında değil, gönderi planlanmadan önce ortaya çıkar.

Platform Gönderi Başlık Metin Hashtag'ler Medya
YouTube Video BaşlıkZorunlu, en fazla 100 karakter AçıklamaEn fazla 5.000 karakter Etiket olarak gönderilir, en fazla 60 MP4, MOV, WebM, AVI, MKV; en fazla 256 GB; 1 sn. ile 12 sa. arası
Telefon numarası doğrulanmamış hesaplar en fazla 15 dakikalık video yükleyebilir ve özel küçük resim ayarlayamaz. Her yükleme API kotası tüketir; varsayılan Google kotası uygulama başına günde yaklaşık altı yüklemeye izin verir.
Instagram Görsel Başlık yok AçıklamaEn fazla 2.200 karakter Metne eklenir, en fazla 30 JPEG; en fazla 8 MB
Video Başlık yok AçıklamaEn fazla 2.200 karakter Metne eklenir, en fazla 30 MP4, MOV; en fazla 300 MB; 3 sn. ile 15 dk. arası
Instagram İşletme veya İçerik Üretici hesabı gerektirir. Instagram, hesap başına kayan 24 saatlik dönemde API üzerinden 50 gönderi yayınlamaya izin verir. Instagram'da yalnızca metin içeren gönderiler mümkün değildir.
TikTok Görsel BaşlıkEn fazla 90 karakter AçıklamaEn fazla 4.000 karakter Metne eklenir JPEG, WebP; en fazla 20 MB
Video Başlık yok AçıklamaEn fazla 2.200 karakter Metne eklenir MP4, MOV, WebM; en fazla 4 GB; 3 sn. ile 10 dk. arası
TikTok denetimini tamamlamamış uygulamaların gönderilerini yalnızca içerik üreticisi görebilir. TikTok kapağı bir video karesinden seçer; özel kapak görselleri desteklenmez. TikTok'ta yalnızca metin içeren gönderiler mümkün değildir.
X Metin Başlık yok GönderiZorunlu, en fazla 280 (bağlantılar 23, emojiler 2 sayılır) Metne eklenir Yok
Görsel Başlık yok GönderiEn fazla 280 (bağlantılar 23, emojiler 2 sayılır) Metne eklenir JPEG, PNG, WebP, GIF; en fazla 5 MB
Video Başlık yok GönderiEn fazla 280 (bağlantılar 23, emojiler 2 sayılır) Metne eklenir MP4, MOV; en fazla 512 MB; 0,5 sn. ile 2:20 dk. arası
Kendi X geliştirici uygulamanızı kullanırsanız gönderiler, uygulamanın kullandıkça öde modelindeki API kredilerini tüketir. Hashtag'ler karakter sınırına dahildir.
Facebook Metin Başlık yok GönderiZorunlu, en fazla 63.206 karakter Metne eklenir Yok
Görsel Başlık yok AçıklamaEn fazla 63.206 karakter Metne eklenir JPEG, PNG, GIF, WebP; en fazla 10 MB
Video BaşlıkEn fazla 255 karakter AçıklamaEn fazla 63.206 karakter Metne eklenir MP4, MOV; en fazla 1 GB; 1 sn. ile 20 dk. arası
Yalnızca Sayfalara yayınlar; API üzerinden kişisel profillerde paylaşım yapılamaz.
Özel API Metin BaşlıkUzunluk sınırı yok AçıklamaUzunluk sınırı yok Etiket olarak gönderilir Yok
Görsel BaşlıkUzunluk sınırı yok AçıklamaUzunluk sınırı yok Etiket olarak gönderilir JPEG, PNG, WebP, GIF
Video BaşlıkUzunluk sınırı yok AçıklamaUzunluk sınırı yok Etiket olarak gönderilir MP4, MOV, WebM
Amaposta'dan geldiğini doğrulayabilmeniz için her istek bir HMAC-SHA256 başlığıyla imzalanır. 2xx ve isteğe bağlı JSON {"id": "…", "url": "…"} ile yanıt verin. 408, 429 ve 5xx yanıtları giderek uzayan aralıklarla yeniden denenir; 401/403 kanalı yeniden bağlanması için işaretler; diğer 4xx yanıtları teslimatı başarısız kılar, böylece düzeltip yeniden deneyebilirsiniz.
Sandbox Metin BaşlıkEn fazla 200 karakter AçıklamaEn fazla 5.000 karakter Metne eklenir, en fazla 30 Yok
Görsel BaşlıkEn fazla 200 karakter AçıklamaEn fazla 5.000 karakter Metne eklenir, en fazla 30 JPEG, PNG, WebP, GIF
Video BaşlıkEn fazla 200 karakter AçıklamaEn fazla 5.000 karakter Metne eklenir, en fazla 30 MP4, MOV, WebM
Yayınlama kısa bir süre alır; böylece durum değişimini canlı izleyebilirsiniz.