Admin API
MarkdownPanelin kullandığı yönetim endpoint'lerine sunucu anahtarıyla istek gönderilmesi; izinler ve ortak liste sözleşmesi.
Panelin kullandığı endpoint’lere (/admin/v1/…) sunucudan sunucuya da istek gönderilebilir; örneğin yorumları kendi veri ambarınıza aktarmak ya da denetim raporunu otomatik olarak oluşturmak için.
Kimlik doğrulama
Bölüm başlığı “Kimlik doğrulama”GET https://api.sayproof.example/admin/v1/reviews?status=publishedAuthorization: Api-Key sp_<önek>_<gizli>Anahtarın hangi endpoint’leri kullanabileceği izinlerine bağlıdır:
| Anahtar izni | Kapsadığı işlemler |
|---|---|
Yorumları okuma (read) |
Yorumları, davetleri, gönderim ve bağlantı kayıtlarını ve istatistikleri görüntüleme |
Yorumlara karar verme (moderate) |
Okuma işlemleri ile onay, ret ve toplu işlem |
Dosya indirme (export) |
Okuma işlemleri ile denetim raporu, işlem geçmişi ve dosya dışa aktarımları (CSV, Excel, JSON) |
Ayarları değiştirme (write) |
Okuma işlemleri ve ayarlar. Bu izni yalnızca Sayproof ekibi verebilir. |
Sayfayı sunucuda hazırlama (ssr) |
Yalnızca SSR ve oturum açmış müşteri endpoint’leri |
Sipariş gönderme (orders) |
Yalnızca sipariş ve teslimat aktarımı endpoint’leri (/v1/ingest/orders, /v1/ingest/deliveries) |
- Panelden oluşturulan sunucu anahtarları “Sipariş gönderme” (
orders) ve “Sayfayı sunucuda hazırlama” (ssr) izinlerini taşır ve Admin API’yi kullanamaz. Panel oturumundaPOST /admin/v1/channelsisteğine{"kind": "api_key", "label": "…"}gönderilipscopesverilmediğinde de anahtar bu iki izinle oluşturulur. Panel izin seçtirmez; okuma, karar verme ya da dosya indirme izni olan bir anahtar, panel oturumunda aynı isteğescopeseklenerek oluşturulur (örneğin"scopes": ["read", "export"]). Boş liste400 invalid / scopes_required, tanınmayan izin400 invalid / unknown_scope: <izin>döner. Ayarları değiştirme (write) iznini yalnızca Sayproof ekibi verebilir; markanın panelinden istendiğinde400 invalid / scope_reserved: writedöner. - Kullanıcı, kanal, anahtar, kişisel veri talebi ve sipariş bağlantısı endpoint’leri hiçbir anahtarla kullanılamaz; bu işlemler yalnızca panel oturumunda ve kullanıcının rolüne göre yapılabilir. Böylece ele geçirilen bir anahtarla yeni anahtar oluşturulamaz, kullanıcı eklenemez ve kişisel veri talebi işlenemez. Bu endpoint’lere anahtarla istek gönderildiğinde
403döner: kullanıcı, kanal, anahtar ve kişisel veri talebi endpoint’lerindeforbidden / scope_missing; sipariş bağlantısı endpoint’lerinde anahtarınwriteizni varsaforbidden / panel_session_required, yoksaforbidden / scope_missing. - Davet gönderim ayarları (
invite_delivery,reminder_delivery,webhook_url,support_url,sender_address) da yalnızca panel oturumunda değiştirilebilir.POST /admin/v1/settingsisteği bu alanlardan birini anahtarla değiştirmeye çalışırsa403 refused / panel_session_requiredyanıtı alır; diğer ayarlar değiştirilebilir. - İzin dışındaki istekler
403, kimlik bilgisi içermeyen ya da geçersiz anahtarla gönderilen istekler401yanıtı alır. Anahtarla yapılan her değişiklik İşlem geçmişi ekranına anahtarın adıyla kaydedilir. Kişisel veri gösteren okumalar (yorum ayrıntısı, yorum geçmişi, davet ve mesaj kayıtları, sorular, e-posta adresiyle arama, ret listesi sorgusu) da İşlem geçmişi › Kişisel veri erişimleri sekmesine anahtarın adıyla yazılır.
Başlıca endpoint’ler
Bölüm başlığı “Başlıca endpoint’ler”| Endpoint | İzin | İşlevi |
|---|---|---|
GET /admin/v1/reviews |
read |
Yorum listesi; satırlar katalogdaki ürün adını product_name olarak taşır (katalogda yoksa boş). q başlıkta, yorum metninde, ürün adında ve kodunda, sipariş numarasında, yazanın adında ve e-posta adresinde arar; tam yorum kimliği verilirse o yorumu döner. ?export=csv, ?export=xlsx ya da ?export=json ile aynı alanları taşıyan CSV, Excel ya da JSON dosyası döner (export izni gerekir). Satırlardaki flag_open, yorumda karar bekleyen bir otomatik kontrol bulgusu olduğunu söyler; source, pazaryerinden aktarılan yorumda {"platform", "name"} (örneğin {"platform": "trendyol", "name": "Trendyol"}), diğer yorumlarda null olur. entry_point=import yalnız aktarılan yorumları listeler. |
GET /admin/v1/reviews/<id> |
read |
Yorum ayrıntısı: yazanın girdiği ad (author, her zaman tam ad) ve yazan adının sitede gizlenmesini isteyip istemediği (name_hidden), satın alma kanıtı, geçmiş, otomatik kontroller, bildirimler ve yapılabilecek işlemler (available_events). Fotoğraf ve video adresleri (media[].url, poster_url, srcset) aşağıdaki dosya endpoint’ini gösterir. |
GET /admin/v1/reviews/<id>/media/<dosya kimliği>/<dosya adı> |
read |
Yorumun fotoğraf ya da videosu (özgün dosya, küçük boyutlar, video kapağı). Yorum yayında olmasa da açılır; yanıt önbelleğe alınmaz (Cache-Control: private, no-store) ve Range header’ı ile parça parça istenebilir. Bilinmeyen dosya ya da başka bir yorumun dosyası 404 not_found döner. |
DELETE /admin/v1/reviews/<id>/media/<dosya kimliği> |
moderate |
Body {"reason"}: yorumun tek bir fotoğrafını ya da videosunu kaldırır. reason personal_data, profanity, data_subject_request ve legal_order değerlerinden biridir (aynı liste GET /admin/v1/reasons yanıtındaki review_media_removal altında ve yorum ayrıntısındaki media_removal_reasons içindedir); gerekçe yoksa ya da tanınmıyorsa 400 invalid / reason_required ya da 400 invalid / reason döner. Dosya hem herkese açık hem kapalı alandan kalıcı olarak silinir; yorumun metni, puanı ve durumu değişmez. Yanıt 204’tür. Kaldırma yorumun geçmişine ve İşlem geçmişi’ne yazılır. Bilinmeyen, daha önce kaldırılmış ya da başka bir yorumun dosyası 404 not_found döner. |
POST /admin/v1/reviews/<id>/transition |
moderate |
Body {"event", "reason"}: onay, ret, gizleme, kaldırma gibi işlemler |
GET /admin/v1/moderation/queue |
moderate |
Onay bekleyen yorumlar; product_name, source ve q araması yorum listesindekiyle aynı. channel=<kanal kodu> verilirse liste ve counters yalnızca o kanalın yorumlarını kapsar; counters.elsewhere (reviews, responses) diğer kanallarda onay bekleyen yorum ve satıcı yanıtı sayısıdır (channel verilmezse ikisi de 0). |
POST /admin/v1/moderation/bulk |
moderate |
Body {"ids", "action": "approve" | "reject", "reason"}; tek istekte en fazla 200 yorum. Onay beklemeyen yorumlar değiştirilmeden atlanır. Yanıt {"count", "skipped"}: işlenen ve atlanan yorum sayısı. |
GET /admin/v1/reviews/<id>/trace |
export |
Yorumun dosyası: {"review", "timeline"}. timeline satırları yorumun ve satıcı yanıtının adımlarını, bildirimleri, çözüm notunu ve ret bildirimlerini (subject_type: "notice") zaman sırasıyla taşır. ?format=csv|xlsx|json dosya olarak indirir ve İşlem geçmişi’ne review_history.downloaded yazar. CSV ve Excel’in yorum bölümünde Panelde aç satırı paneli bu yorum açık hâlde açan adresi taşır; JSON’da bu alan yoktur. |
POST /admin/v1/reviews/<id>/reports/resolve |
moderate |
Body {"note"} (isteğe bağlı, en fazla 1000 karakter): yorumun açık bildirimlerini kapatır. Yanıt {"closed"} kapatılan bildirim sayısıdır. |
GET /admin/v1/reasons |
read |
Gerekçe listeleri, istenen dilde; review_media_removal tek bir fotoğrafı ya da videoyu kaldırma gerekçelerini taşır |
GET /admin/v1/metrics, GET /admin/v1/insights |
read |
İstatistikler. channel=<kanal kodu> verilirse sayılar yalnızca o kanalı kapsar; tanınmayan kanal kodu 400 invalid / channel alır. GET /admin/v1/insights isteğinde market ile birlikte verilen kanal o pazara ait değilse 400 invalid / channel_market_mismatch döner. GET /admin/v1/insights yanıtındaki ai alanı yapay zekâ paketinin dönem özetidir (v2 ile gelecek; şu an null döner). |
GET /admin/v1/invites, GET /admin/v1/send-logs |
read |
Davetler ve mesaj kayıtları. Davet listesinde sent=1 yalnızca e-postası gönderilmiş davetleri getirir; channel=<kanal kodu> verilirse liste ve counters o kanalın siparişleriyle sınırlanır. Mesaj kayıtlarında q alıcının adresinde de arar; channel_kind (email ya da webhook; whatsapp v2 ile gelecek, şu an bu yolla mesaj gönderilmez) gönderim yoluna göre süzer; channel=<kanal kodu> liste ve counters’ı o kanalın mesajlarıyla sınırlar (davet siparişin, ret bildirimi yorumun, cevap bildirimi sorunun kanalına göre). Müşterinin kişisel verileri KVKK talebiyle silinmişse recipient boş, recipient_erased true döner. Davetlerin counters.conversion değeri gönderilmiş davetlerden en az bir ürünü yorumlanmış olanların oranıdır. |
POST /admin/v1/invites/retry |
write |
“Gönderilemedi” durumundaki davetleri yeniden sıraya alır. Body isteğe bağlıdır: {"ids": […]} (en fazla 500 davet) ve {"channel": "<kanal kodu>"} (yalnızca o kanalın davetleri); ikisi de gönderilmezse tümü. Bağlantısının süresi dolmuş davetler atlanır. Yanıt {"queued", "expired"}. |
GET /admin/v1/diagnostics |
read |
Bağlantı kayıtları |
POST /admin/v1/opt-outs/check |
read |
Body {"addresses": […]} (tek istekte en fazla 1.000 adres): listedeki adreslerden e-posta almak istemeyenleri döndürür: {"opted_out": [{"address", "channel_kind", "reason", "created_at"}]}. Telefon numarası uluslararası (+905321112233) ya da kanallarınızın pazarındaki yerel yazımla (0532 111 22 33) verilebilir; yanıtta gönderdiğiniz yazım döner. |
GET /admin/v1/opt-outs/export |
export |
E-posta almak istemeyenler listesinin tamamını indirir; ?format=csv (varsayılan), ?format=xlsx ya da ?format=json. Dosya adresin kendisini değil, küçük harfe çevrilmiş e-posta adresinin SHA-256 değerini taşır (address_hash, channel_kind, reason, created_at). WhatsApp satırlarındaki (v2 ile gelecek; şu an liste telefon satırı içermez) telefon numaraları Sayproof’a özgü anahtarlı bir karmayla saklanır ve dosyada bu değerle yer alır; telefon listenizi eşleştirmek için POST /admin/v1/opt-outs/check ucunu kullanın. Her indirme İşlem geçmişi’ne kaydedilir. |
GET /admin/v1/policies |
read |
Markanın gördüğü pazar kuralı sürümleri (profiles; Sayproof kuralları ve markanın kendi sürümleri, own, in_force, scheduled) ve pazar başına sınırlar (limits). channel=<kanal kodu> verilirse yalnızca o kanalın pazarının ve o kanalın kuralları döner. Yeni sürüm (POST) yalnızca panel oturumunda, “Pazar kurallarını yönetebilir” izniyle açılır: Kuralların güncellenmesi. |
GET /admin/v1/method-statement |
read |
Her açık kanal ve dil için yöntem beyanı satırları (rows) ve kendi sayfanız için kullanılabilecek doğrulanmış alan adları (domains). Her satır channel, channel_label, market, language, state, external_url, hosted_url, effective_url, current_fingerprint, confirmed ve beyan metnini (statement) taşır. ?channel=<kanal kodu>&lang=tr tek kanalın beyanını ve kendi sayfanızın durumunu döner. Tanınmayan kanal kodu 400 invalid / channel alır. |
POST /admin/v1/method-statement, POST /admin/v1/method-statement/confirm |
write |
Kendi sayfanızın adresini kaydeder: body {"channel", "language", "external_url"}; boş external_url bağlantıyı Sayproof sayfasına döndürür. Onay: body {"channel", "language", "fingerprint"}; fingerprint satırdaki current_fingerprint değeridir, metin bu arada değiştiyse 409 statement_changed döner. Tanınmayan kanal kodu 400 invalid / channel alır. |
POST /admin/v1/audit-file |
export |
Body {"market", "channel", "start", "end"}: denetim raporunu oluşturur ve saklar. market ve channel boşsa rapor bütün kanalları, yalnız market verilirse o pazarın bütün kanallarını, channel verilirse yalnızca o kanalı kapsar; pazar kanaldan alınır. Tanınmayan kanal kodu 400 invalid / channel, kanalın pazarıyla uyuşmayan market 400 invalid / channel_market_mismatch alır. Saklanan rapor ve dosya adı kanal kodunu taşır; önceki raporlar listesi channel filtresiyle süzülür. |
GET /admin/v1/audit-file/<id>?format=json|csv|xlsx |
export |
Saklanan raporu indirir; X-Sayproof-Fingerprint header’ı doğrulama kodudur. CSV ve Excel’de kaldırılan ve gizlenen yorumların satırlarında Panelde aç sütunu bulunur; Excel’de adresler tıklanabilir. |
GET /admin/v1/audit-log |
export |
İşlem geçmişi. Paneldeki İndir menüsü dosyayı POST /admin/v1/audit-log/export ile Sayproof’a ürettirir: body {"format", "title", "filters", "columns", "labels", "changes"}. Satırlar sunucuda, listedeki filtrelerin (filters) aynısıyla bu kayıtlardan okunur; en fazla 10.000 kayıt. columns sekiz sütunun adını, labels işlem, rol ve hedef kodlarının ekrandaki adlarını (action, role, target) ve system sözcüğünü, changes kayıt numarasına göre Ne değişti metnini taşır; son sütun işlemin kodudur. İndirme aynı istekte İşlem geçmişi’ne audit_log.downloaded işlemi olarak biçimi, satır sayısı ve dosyanın SHA-256 hash’iyle (fingerprint) kaydedilir. Bozuk istek 400 invalid / rows, 10.000’i aşan kayıt 400 invalid / rows_over_limit döner. |
GET /admin/v1/access-log |
export |
Kişisel veri erişimleri (İşlem geçmişi › Kişisel veri erişimleri). Satırlar action (review.viewed, reviews.searched, review_history.viewed, invites.listed, send_logs.listed, questions.listed, question.viewed, subject_requests.listed, subject_request.viewed, subject_request.previewed, users.listed, opt_out.checked, imported_reviews.listed), actor_id, actor_role, via (session, api_key, support, console), target_type, target_id, count (o okumada dönen ve kişisel veri taşıyan kayıt sayısı) ve at taşır. Süzgeçler action, actor, via; q kişide ve kayıt numarasında arar. Kayıtlar değiştirilemez ve 365 gün sonra silinir. |
GET|POST /admin/v1/invite-templates |
write |
Davet e-postası şablonları. Satırlar channel alanını taşır (kanal kodu; tüm kanallar için hazırlanmış şablonda boş). Kayıtta channel verilirse şablon yalnız o kanalın siparişlerinde kullanılır ve market kanaldan alınır; tanınmayan kanal kodu 400 invalid / channel alır. |
GET /admin/v1/questions |
read |
Soru listesi. Süzgeçler: state, market, channel, unanswered=1, answers_waiting=1; q soru metninde, soranın adında ve e-posta adresinde, ürün kodunda arar. Yanıt ayrıca counters (waiting, unanswered, answers_waiting) ve markanın soru-cevabı açık mı (enabled) bilgisini taşır. |
GET /admin/v1/questions/<id> |
read |
Soru ayrıntısı: soranın adı (asker_name, tam ad) ve adının sitede gizli kalıp kalmayacağı (name_hidden), cevaplar (her biri author_name ve name_hidden taşır), her cevabın soran kişiye giden e-postasının sonucu (notice), yapılabilecek işlemler (available_events) ve geçmiş (ledger) |
POST /admin/v1/questions/<id>/transition, POST /admin/v1/answers/<id>/transition |
moderate |
Body {"event", "reason"}: onay, ret, yeniden inceleme, gizleme ve yeniden gösterme |
POST /admin/v1/questions/<id>/answer |
moderate |
Body {"body"}: yayındaki soruya marka cevabı yazar ve hemen yayınlar; yanıt 201 ile cevabın satırıdır. Cevap denetimden geçmezse 409 answer_refused (text_steering, text_health_claim, text_personal_data, text_profanity, question_not_published). |
POST /admin/v1/reviews/<id>/seller-response/draft |
moderate |
Yapay zekâ paketiyle satıcı yanıtı taslağı (v2 ile gelecek; şu an 409 seller_response_refused döner, detail ai_package_off ya da ai_feature_closed): body {"tone"} isteğe bağlı (formal ya da warm; verilmezse markanın varsayılan tonu), yanıt {"draft"}. Taslak kaydedilmez. |
GET /admin/v1/ai |
read |
Yapay zekâ paketinin durumu (v2 ile gelecek; şu an 404 döner). Paket talebi POST /admin/v1/ai/requests de v2 ile gelecek; şu an 404 döner. |
GET|POST /admin/v1/settings |
write |
Ayarlar. Yanıttaki time_zone, gönderim saatlerinin uygulandığı saat dilimidir (örneğin Europe/Istanbul). Diğer alanlar arasında questions_enabled, reply_tone (formal ya da warm), ai_translation_enabled, ai_summary_enabled (bu üçü v2 ile gelecek; şu an kaydedilir ama etkisi yoktur), syndication_enabled, reminder_consent (not_required ya da required) ve kurulumda seçilebilen gönderim yolları (deliveries) bulunur. Gönderim yolu alanları (invite_delivery, reminder_delivery, webhook_url, support_url, sender_address) yalnızca panel oturumunda değiştirilir; anahtarla 403 refused / panel_session_required. Kurulumda kapalı bir yol seçilirse 400 invalid / invite_delivery_unavailable ya da reminder_delivery_unavailable. |
Kişisel veri talepleri
Bölüm başlığı “Kişisel veri talepleri”Kişisel veri talebi endpoint’leri hiçbir anahtarla kullanılamaz; yalnızca panel oturumunda ve “KVKK taleplerini yürütebilir” izni olan kullanıcıyla çalışır. Talep kaydı müşterinin e-posta adresini düz olarak saklamaz; erişim talebinde hazırlanan verilerin kopyası da saklanmaz.
Talep satırları (GET /admin/v1/subject-requests listesindeki satırlar ve talep yanıtları) can_copy alanını taşır. Değer true ise talep tamamlanmış bir erişim talebidir ve kopyası yeniden alınabilir.
POST /admin/v1/subject-requests/<id>/copy, tamamlanmış bir erişim talebinin kopyasını güncel kayıtlardan yeniden hazırlar. Body’de talepteki müşterinin e-posta adresi gönderilir:
POST https://api.sayproof.example/admin/v1/subject-requests/<id>/copyContent-Type: application/json
{"identifier": "ayse@ornek.com", "format": "xlsx"}format gönderilmezse yanıt JSON gövdesidir; csv, xlsx ya da json gönderilirse aynı içerik dosya olarak döner (CSV ve Excel düzeni: Erişim dosyası).
| Yanıt | Anlamı |
|---|---|
200 |
Talebin bilgileri (id, kind, state, received_at, completed_at, affected_reviews, purged_media) ile export ve export_details alanları. Talebe yazılan not ve talebi işleyen kullanıcı kopyaya girmez; içerik için: Erişim dosyası. |
400 invalid / identifier_required |
identifier gönderilmemiş ya da boş |
400 identifier_mismatch |
Adres, talep kaydındaki adresle eşleşmiyor; kopya verilmez |
400 invalid / format |
format değeri csv, xlsx ya da json değil |
404 not_found |
Bu kimlikte bir talep yok |
409 not_copyable |
Talep tamamlanmış bir erişim talebi değil |
Her başarılı istek İşlem geçmişi’ne subject_request.copied işlemiyle kaydedilir; ekranda “KVKK erişim talebinin kopyası indirildi” olarak görünür.
Her talebin kaydı GET /admin/v1/subject-requests/<id> ile okunur; ?format=csv, ?format=xlsx ya da ?format=json kaydı dosya olarak indirir. Bu indirme İşlem geçmişi’ne subject_request.downloaded işlemiyle (“KVKK talebinin kaydı indirildi”) yazılır.
Sipariş bağlantıları
Bölüm başlığı “Sipariş bağlantıları”Akinon, Shopify ve WooCommerce gibi platformlardan sipariş okuyan bağlantıların endpoint’leri hiçbir anahtarla kullanılamaz; yalnızca panel oturumunda ve “Ayarları değiştirebilir” izni olan kullanıcıyla çalışır. Paneldeki karşılığı ve okuma kuralları: Akinon siparişleri, Shopify siparişleri, WooCommerce siparişleri.
| Endpoint | İşlevi |
|---|---|
GET /admin/v1/order-sources |
Bağlantılar (items) ve hazır bağlantısı olan platformlar (platforms; her platformun bağlantı alanları fields içinde) |
POST /admin/v1/order-sources |
Bağlantı kurar. Body: platform, channel ve platformun bağlantı alanları (Akinon: base_url, remote_channel, username, password; Shopify: base_url, client_secret, isteğe bağlı client_id; WooCommerce: base_url, consumer_key, consumer_secret); isteğe bağlı backfill_days (1–365, varsayılan 30), interval_minutes (5–1440, varsayılan 15) ve enabled |
POST /admin/v1/order-sources/check |
Kaydetmeden dener. Body kurulumla aynıdır, channel gerekmez. |
GET|PATCH|DELETE /admin/v1/order-sources/<id> |
Bağlantıyı gösterir, değiştirir (enabled, interval_minutes, backfill_days ve platformun bağlantı alanları; giriş bilgileri yalnızca gönderilirse değişir, base_url başka bir adrese değişirse giriş bilgileri de yeniden gönderilmelidir) ya da kaldırır |
POST /admin/v1/order-sources/<id>/check |
Kayıtlı bilgilerle dener |
POST /admin/v1/order-sources/<id>/run |
Okumayı hemen başlatır ve 202 döner; duraklatılmış bağlantıda 409 source_inactive, kanal kapalıyken 409 channel_inactive |
Yanıtlarda giriş bilgileri (parola, Client secret, Consumer key ve Consumer secret gibi) hiçbir zaman yer almaz; giriş bilgisi olmayan alanlar values içinde döner, has_credentials alanı kayıtlı giriş bilgisi olup olmadığını gösterir. channel_active bağlantının kanalının açık olup olmadığını bildirir; kanal kapalıyken bağlantı okuma yapmaz. Deneme yanıtı müşteri e-postasını içermez, yalnızca var olup olmadığını (has_email) bildirir:
{ "orders": 3, "complete": true, "skipped": {"status_unknown": 1}, "sample": [ {"external_id": "100234", "placed_at": "2026-09-28T10:12:00+00:00", "payment_state": "paid", "lines": 2, "states": ["delivered"], "has_email": true} ]}skipped okunamayan siparişleri nedene göre sayar: order_incomplete (numarası ya da tarihi eksik), status_unknown (durumu tanınmıyor), line_incomplete (ürün satırında ürün kodu eksik), order_without_lines (okunabilen ürün satırı yok) ve yalnızca Shopify’da lines_truncated (50’den fazla ürün satırı var; ilk 50 satır okundu). Bağlantının son okuma özetinde (last_report.skipped) Sayproof’a kaydedilemeyen siparişler order_refused ile sayılır.
Pazaryeri yorumları
Bölüm başlığı “Pazaryeri yorumları”Pazaryerlerinden yorum alan bağlantıların endpoint’leri hiçbir anahtarla kullanılamaz; yalnızca panel oturumunda ve “Ayarları değiştirebilir” izni olan kullanıcıyla çalışır. Yorumları listeleyen ve kaldıran iki endpoint de hiçbir anahtarla kullanılamaz; yalnızca panel oturumunda ve “KVKK taleplerini yürütebilir” izni olan kullanıcıyla çalışır. Panelde ve kuralları: Pazaryeri yorumları.
| Endpoint | İşlevi |
|---|---|
GET /admin/v1/marketplace/sources |
Bağlantılar (items; her biri last_run, runs ve attention taşır; attention kaldırması bekletilen bağlantıda held, üst üste okunamayan bağlantıda failed türünü, sayıyı ve son hata kodunu verir, sorun yoksa null olur), pazaryerleri (platforms) ve alış yolları (routes) |
POST /admin/v1/marketplace/sources |
Bağlantı kurar. Body: platform (trendyol, hepsiburada, amazon, n11, ciceksepeti), channel, seller_id, route (file ya da feed); feed yolunda feed_url (https) ve isteğe bağlı secret. Kurulum kimin yaptığıyla İşlem geçmişi’ne yazılır. Aynı kanal, pazaryeri ve satıcı numarası için ikinci bağlantı 409 source_exists alır. |
GET|PATCH|DELETE /admin/v1/marketplace/sources/<id> |
Bağlantıyı gösterir, değiştirir (enabled; feed yolunda feed_url ve secret; seller_id değiştirilemez, 400 seller_id_locked) ya da kaldırır (yayında aktarılmış yorum ya da kişisel veri talebiyle kaldırılmış yorum kaydı varsa 409 source_has_reviews). secret yanıtlarda dönmez; has_secret kayıtlı olup olmadığını gösterir. |
POST /admin/v1/marketplace/sources/<id>/runs |
Okumayı başlatır ve 202 döner. file yolunda multipart/form-data ile file (CSV, .xlsx ya da JSON; en çok 20 MB, 100.000 satır) gönderilir; dosya tam bir karşılaştırmadır. feed yolunda body: scope (new ya da full, varsayılan full). İkisinde de confirm_removals (true ise bekletilen kaldırmalar uygulanır). Başka okuma sürerken 409 run_in_progress, duraklatılmış bağlantıda ya da kapalı kanalda 409 source_inactive. Dosya okunamazsa 400 ve detail içinde column_missing: <sütun>, file_unreadable, unsupported_format, too_large ya da too_many_rows. |
GET /admin/v1/marketplace/sources/<id>/runs |
Son okumalar; her okumanın sayıları ve report içinde eşleşme raporu |
POST /admin/v1/marketplace/sources/<id>/check |
Hiçbir şey kaydetmeden dener: file yolunda file gönderilir, feed yolunda adres okunur. Yanıt: rows, eligible, would_import, would_update, would_remove, matched_barcodes, unmatched_barcodes, unmatched, skips. |
GET /admin/v1/marketplace/imported-reviews |
Aktarılmış yorumları listeler; q yorum metninde, yazar adında ve pazaryeri yorum numarasında arar, platform süzer. |
POST /admin/v1/marketplace/removals |
Seçilen aktarılmış yorumları kişisel veri talebiyle kaldırır. Body: reviews (aktarılmış yorum kimlikleri, en çok 100), isteğe bağlı note. Yanıt 201: id, reviews, media_purged, state. Talep Kişisel veri talepleri listesine silme olarak yazılır. |
Okuma satırında state queued, running, succeeded, held (kaldırmalar bekletildi) ya da failed olur; error başarısız okumanın kodudur. report matched_barcodes, unmatched_barcodes, unmatched (barcode, reason: no_product, no_barcode ya da ambiguous, reviews), skips, photos_missing ve bekletilmiş okumada held_products taşır.
Ortak liste sözleşmesi
Bölüm başlığı “Ortak liste sözleşmesi”Liste endpoint’leri aynı parametreleri ve aynı yanıt biçimini kullanır.
Parametreler: endpoint’te tanımlı her filtrenin adı, q (arama), from ve to (tarih ya da tam zaman; yalnızca tarih verilirse o günün tamamı dahil edilir), sort, page ve page_size (en fazla 100).
{ "items": [], "total": 0, "page": 1, "pages": 1, "facets": { "state": [{ "value": "sent", "count": 12 }] }, "filters": [{ "name": "state", "group": "invite_state", "faceted": true, "advanced": false, "kind": "value" }], "sorts": ["oldest", "recent"]}filters, endpoint’in kabul ettiği filtreleri listeler.kindfiltrenin türünü belirtir:value(değer listesi),flag(=1) ya dachoice(adlandırılmış seçenekler).facets, her filtrenin değerlerini o filtrenin kendisi hariç tutularak sayar.
Yanıtlardaki değerler kod olarak döner (published, profanity vb.). Ekranda göstermek için gerekçe ve durum adlarını GET /admin/v1/reasons yanıtı ve kendi çeviri dosyalarınızla metne dönüştürün.
Örnekler
Bölüm başlığı “Örnekler”Yayındaki yorumları sayfa sayfa almak (Python)
Bölüm başlığı “Yayındaki yorumları sayfa sayfa almak (Python)”import os
import requests
BASE = os.environ["SAYPROOF_BASE"]HEADERS = {"Authorization": f"Api-Key {os.environ['SAYPROOF_ADMIN_KEY']}", "Accept-Language": "tr"}
def published_reviews(since): page = 1 while True: answer = requests.get( f"{BASE}/admin/v1/reviews", params={"status": "published", "from": since, "sort": "oldest", "page": page, "page_size": 100}, headers=HEADERS, timeout=30, ) answer.raise_for_status() body = answer.json() yield from body["items"] if page >= body["pages"]: return page += 1
for review in published_reviews("2026-09-01"): print(review["id"], review["rating"])Denetim raporu oluşturup doğrulamak (Node.js)
Bölüm başlığı “Denetim raporu oluşturup doğrulamak (Node.js)”import { createHash } from "node:crypto";import { writeFile } from "node:fs/promises";
const base = process.env.SAYPROOF_BASE;const headers = { Authorization: `Api-Key ${process.env.SAYPROOF_EXPORT_KEY}`, "Content-Type": "application/json" };
const created = await fetch(`${base}/admin/v1/audit-file`, { method: "POST", headers, body: JSON.stringify({ market: "TR", start: "2026-09-01", end: "2026-09-30" }),}).then((answer) => answer.json());
const download = await fetch(`${base}/admin/v1/audit-file/${created.copy.id}?format=json`, { headers });const content = Buffer.from(await download.arrayBuffer());const fingerprint = download.headers.get("X-Sayproof-Fingerprint");
if (createHash("sha256").update(content).digest("hex") !== fingerprint) { throw new Error("audit_file_fingerprint_mismatch");}await writeFile(`denetim-${created.copy.id}.json`, content);JSON dosyasının SHA-256 değeri doğrulama koduyla aynıdır; dosyanın indirildikten sonra değiştirilmediğini bu karşılaştırmayla gösterebilirsiniz.
E-posta almak istemeyen adresleri sorgulamak (Python)
Bölüm başlığı “E-posta almak istemeyen adresleri sorgulamak (Python)”Kendi e-posta gönderimlerinizden önce, Sayproof’taki listede yer alan adresleri ayıklamak için adresleri 1.000’erli gruplar hâlinde sorgulayın. Yanıt yalnızca listede bulunan adresleri döndürür.
import os
import requests
BASE = os.environ["SAYPROOF_BASE"]HEADERS = {"Authorization": f"Api-Key {os.environ['SAYPROOF_ADMIN_KEY']}"}
def opted_out(addresses): found = set() for start in range(0, len(addresses), 1000): answer = requests.post( f"{BASE}/admin/v1/opt-outs/check", json={"addresses": addresses[start : start + 1000]}, headers=HEADERS, timeout=30, ) answer.raise_for_status() found |= {row["address"] for row in answer.json()["opted_out"]} return found