BuyPost API — מדריך למפתחים

קריאת המחירון, שליחת הזמנות, מעקב, אישור כתבות, וביטול או שינוי פרטים בשלבים שבהם האתר מאפשר — מהמערכת שלכם. הרכישה עצמה נעשית באתר (קרדיטים או כרטיס). אחרי התשלום ההזמנה עוברת בדיוק את אותו תהליך כמו הזמנה באתר.

הגישה פתוחה ללקוחות שאושרו: מגישים בקשה ויוצרים מפתח בעמוד API באזור האישי.

לכלי AI ולמפתחים: תיאור מלא בפורמט OpenAPI — customer-api-openapi.json, ומדריך טקסט שכולל מתכון לבניית מערכת שליטה — customer-api.txt. מדריך חיבור לפי כלי (Claude Code, ChatGPT, Cursor, n8n) — חיבור לכלי AI ולסוכנים.

חיבור

  • כתובת אחת: https://ai.buypost.co.il/functions/customerApi, בקשות POST עם גוף JSON שכולל action.
  • המפתח נשלח בכותרת Authorization: Bearer bp_live_… בלבד — לא בכתובת ולא בגוף. השתמשו בו רק מהשרת שלכם.
  • תשובה מוצלחת: { "ok": true, "data": … } (בפעולות שליחה יש גם message בעברית). שגיאה: { "ok": false, "error": { "code", "message", "hint", "details" } } — hint אומר מה לעשות.
  • סכומים בשקלים. *_before_vat — לפני מע"מ (כמו הקרדיטים); *_incl_vat — כולל מע"מ (תשלום בכרטיס). המחיר תמיד מחושב אצלנו.
curl -X POST https://ai.buypost.co.il/functions/customerApi \
  -H "Authorization: Bearer bp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"price_list","limit":20}'

מגבלות שימוש

  • עד 10 בקשות בדקה ו-300 בקשות ביום לחשבון (כל המפתחות יחד). כל בקשה נספרת, גם ping. כמה נשאר היום — ב-meta.requests_left_today בכל תשובה.
  • מכסת כתבות ביום (ברירת מחדל 30) ומספר הזמנות שמחכות לתשלום בבת אחת (ברירת מחדל 5). המגבלות של החשבון מוחזרות ב-balance; אפשר לבקש להגדיל.
  • 20 ניסיונות עם מפתח שגוי מאותה כתובת בתוך 10 דקות — חסימה ל-10 דקות.
  • בלי בדיקות חוזרות: הגדירו webhook. כשצריך לבדוק — list_items עם updated_since (רק מה שהשתנה) או get_items (עד 50 כתבות בבקשה אחת), ולא בקשה נפרדת לכל כתבה.
  • תשובות קריאה עשויות להגיע מזיכרון קצר (meta.cached). כל שינוי שלכם, כל שינוי סטטוס של כתבה וכל קניית קרדיטים מרעננים אותו מיד.

פעולות

ping

בדיקת חיבור. מחזיר את החשבון שהמפתח שייך לו.

{ "action": "ping" }

balance

יתרת הקרדיטים (לפני מע"מ), מי משלם (חשבון אישי או סוכנות) ומגבלות השימוש של החשבון.

{ "action": "balance" }

price_list

המחירון — קריאה בלבד, עם כל מה שמוצג באתר: המחיר שלכם (מבצע / מחיר מיוחד / הנחה קבועה כבר מחושבים), מחיר המחירון ומחיר המבצע, DR ו-UR, לוגו, תיאור והערות, תווית דרגה, מאפיינים (למשל dofollow), "פרסום מיידי", כתבות לדוגמה, עיר ואזור, נושאים מומלצים, כללי כתיבה ופרסום, "בשיתוף עם", אישור תמונה, טיוטה מהאתר ופיקסל. בתשובה גם general_restrictions — ההגבלות הכלליות שמוצגות באתר מתחת לכל אתר. סינון: search, category, region, city, language, min_dr, tier, feature, on_sale, instant_publishing, max_price; מיון: sort = price_asc / price_desc / dr_desc; דפדוף: limit (עד 500), offset. מומלץ לשמור אצלכם — המחירון משתנה לעיתים רחוקות.

{ "action": "price_list", "search": "חדשות", "min_dr": 30, "sort": "price_asc", "limit": 50 }

quote

בדיקת הזמנה ומחיר — בלי ליצור כלום. אותם שדות כמו create_order. כתבה מוכנה בלי אף קישור (כל כתובת אתר, מייל או טלפון נחשבים קישור) מקבלת אזהרה שלא חוסמת (warnings, קוד no_external_link) — גם ב-create_order ועל הכתבה עצמה.

{ "action": "quote", "items": [ ... ] }

create_order

שליחת הזמנה עם כל פרטי הכתבות. ההזמנה נוצרת כממתינה לתשלום — לא מחויב כלום. הלקוח משלם באתר ב"הזמנות שלא שולמו" (קרדיטים או כרטיס), ואז הכתבות נכנסות לעבודה. חובה idempotency_key ייחודי: שליחה חוזרת עם אותו מפתח מחזירה את ההזמנה המקורית. עד 20 כתבות בהזמנה.

{
  "action": "create_order",
  "idempotency_key": "crm-order-10457",
  "items": [
    {
      "website_id": "<id מתוך price_list>",
      "content": { "type": "ai" },
      "article_topic": "איך בוחרים צלם לחתונה בקיץ",
      "writing_style": "seo_with_brand",
      "brand_name": "סטודיו אור",
      "keywords": "צילום חתונות",
      "target_link": "https://example.co.il/weddings",
      "scheduled_date": "2026-10-20",
      "notes": "בלי להזכיר מחירים"
    },
    {
      "website_id": "<id>",
      "content": { "type": "html", "html": "<h1>כותרת</h1><p>הכתבה המוכנה שלכם...</p>" },
      "keywords": "עורך דין גירושין",
      "target_link": "https://example.co.il"
    }
  ]
}

get_order

הזמנה אחת: האם שולמה (payment.status), הסכומים, והכתבות שלה עם השלבים ומצב התשלום של כל כתבה.

{ "action": "get_order", "order_id": "<id>" }

list_orders

כל ההזמנות של החשבון — מהאתר ומה-API, מהחדשה לישנה: מספר הזמנה, מצב תשלום, סכומים, מקור (site / api), כמה כתבות, כמה פורסמו, כמה ממתינות לכם, ספירה לפי שלב, ורשימת הכתבות עם השלב וקישור הפרסום. סינון: payment_status (paid / awaiting_payment / cancelled), source (site / api), created_from / created_to (YYYY-MM-DD), search (מספר הזמנה), updated_since; דפדוף: limit (עד 100), offset.

{ "action": "list_orders", "payment_status": "paid", "created_from": "2026-09-01" }

list_items

הכתבות של החשבון, מהחדשה לישנה, עם סטטוס, מצב תשלום, שלבים ותאריכים וכתובת הפרסום. סינון: status, order_id, created_from / created_to (YYYY-MM-DD), waiting_for_you: true (כל מה שמחכה לכם: אישור כתבה, טיוטה באתר, אישור תמונה, נושא שהוחזר לעדכון), awaiting_redemption: true (נקנו ושולמו ומחכות למימוש); updated_since — רק מה שהשתנה מאז הבדיקה הקודמת (שלחו את checked_at שקיבלתם); דפדוף: limit (עד 200), offset.

{ "action": "list_items", "updated_since": "2026-10-02T08:00:00Z" }

get_items

עד 50 כתבות בבקשה אחת — במקום בקשה לכל כתבה. חוסך בקשות מהמכסה.

{ "action": "get_items", "item_ids": ["<id1>", "<id2>"] }

list_redeemable

מה נקנה ועדיין לא נוצל: יתרת הקרדיטים ורכישות אחרונות, כתבות שנקנו ושולמו ומחכות למימוש (לפי אתר), הזמנות שממתינות לתשלום וכמה מהן היתרה מכסה, והמלצה לקנות קרדיטים כשהיתרה לא מספיקה. אותו מידע שמופיע באתר.

{ "action": "list_redeemable" }

get_item

כתבה אחת. כשהכתבה הגיעה לאישורכם מוחזר גם content_html — הטקסט לקריאה.

{ "action": "get_item", "item_id": "<id>" }

approve

אישור כתבה שממתינה לאישורכם (סטטוס review) — בדיוק כמו "מאשר כתבה" באתר.

{ "action": "approve", "item_id": "<id>" }

request_fix

בקשת תיקון מהצוות לכתבה שממתינה לאישורכם. הכתבה המתוקנת חוזרת אליכם.

{ "action": "request_fix", "item_id": "<id>", "note": "להוסיף פסקה על..." }

submit_edit

עריכה עצמית של כתבה שממתינה לאישורכם: שולחים את הטקסט המתוקן (HTML, 300 תווים לפחות). נשמר כמו בעורך באתר — עם קובץ Word תואם, כך שלאתר תמיד נשלחת הגרסה שערכתם. ברירת מחדל: עובר לבדיקת הצוות. keep_for_review: true — הכתבה נשארת אצלכם (כמו "שמירה" באתר) לקריאה ולעריכה נוספת, וכשתאשרו (approve) הצוות יבדוק את השינויים.

{ "action": "submit_edit", "item_id": "<id>", "content_html": "<p>...</p>", "keep_for_review": true }

ai_fix

תיקון באמצעות AI, כמו באתר: כותבים מה לשנות (instructions) וה-AI מתקן את הכתבה — שומר על המבנה, הסגנון, הקישורים ומילות המפתח. הכתבה המתוקנת חוזרת בתשובה (content_html) ונשארת אצלכם: אפשר לאשר, לתקן שוב, לערוך בעצמכם או לבקש מהצוות. אחרי האישור הצוות בודק את השינויים. עד 5 תיקונים לכתבה ו-20 ביממה לחשבון (התשובה מראה כמה נשארו). אם ה-AI נכשל — הכתבה לא משתנה.

{ "action": "ai_fix", "item_id": "<id>", "instructions": "לקצר את הפתיח ולהוסיף פסקה על שעות הפתיחה" }

replace_file

החלפת כתבה שממתינה לאישורכם בקובץ Word משלכם (עד 8MB).

{ "action": "replace_file", "item_id": "<id>", "filename": "article.docx", "file_base64": "..." }

reject_content

דחיית הכתבה שנכתבה: חוזרת לצוות לכתיבה מחדש עם הסיבה (חובה), והכתבה החדשה חוזרת לאישורכם. לביטול הכתבה עצמה — cancel, במקום שהאתר מאפשר.

{ "action": "reject_content", "item_id": "<id>", "reason": "הטון לא מתאים למותג" }

cancel

ביטול כתבה — באותם שלבים שבהם האתר מאפשר: לפני תחילת הכתיבה, או כשהצוות ביקש תיקון. כתבה בהזמנה שעוד לא שולמה אפשר לבטל תמיד (הסכום לתשלום יורד). זיכוי על כתבה ששולמה — לפי התקנון, לקרדיטים.

{ "action": "cancel", "item_id": "<id>", "reason": "..." }

update_item

שינוי פרטים — רק כשהאתר מאפשר: בהזמנה שעוד לא שולמה (כל פרטי הכתבה); תאריך פרסום (scheduled_date, או null לביטול התזמון) לפני שהכתבה נשלחה לאתר; פרטי כתבה כשהצוות החזיר את הנושא לעדכון; או מימוש כתבה שנקנתה ושולמה (redeem). שדות: article_topic, keywords, target_link, keywords_2, target_link_2, writing_style, brand_name, target_audience, notes, client_label, image, scheduled_date. האתר והמחיר לא משתנים. שדות נוספים: shared_with, shared_company_id, team_notes. כתבה של הזמנת אתר שלא שולמה או בוטלה מחזירה order_not_paid (הזמנת API שלא שולמה — אפשר לערוך בחופשיות).

{ "action": "update_item", "item_id": "<id>", "changes": { "scheduled_date": "2026-11-01" } }

redeem

מימוש כתבה שנקנתה מראש ושולמה (awaiting_redemption): שולחים נושא, מילת מפתח, קישור וסגנון כתיבה, ואפשר גם תאריך פרסום — והכתבה נכנסת לעבודה. תאריך לבד לא מממש (redeem_details_required).

{ "action": "redeem", "item_id": "<id>", "changes": { "article_topic": "איך בוחרים צלם לחתונה", "keywords": "צלם חתונות", "target_link": "https://example.co.il", "writing_style": "professional" } }

נעשה רק באתר (מחזיר site_only): תשלום, קניית קרדיטים והגדרת webhook. ביטול ושינוי פרטים בשלב שגם האתר לא מאפשר מחזירים not_cancellable / not_editable עם הסבר.

שדות של כתבה

  • content.type: ai — אנחנו כותבים (חובה article_topic של 3 מילים לפחות ו-writing_style); html — כתבה מוכנה כטקסט HTML (300 תווים לפחות, בלי script/iframe); docx — קובץ Word: filename ו-file_base64 (עד 8MB).
  • writing_style: professional, marketing, seo_no_brand, seo_with_brand, ai_engines. ל-seo_with_brand חובה brand_name. באתר "SEO בלבד" רק seo_no_brand.
  • keywords + target_link — חובה בכתבה שאנחנו כותבים (מילת מפתח אחת, בלי פסיקים). keywords_2 + target_link_2 — רק יחד, ולא באתרים שמתירים קישור אחד.
  • scheduled_date (YYYY-MM-DD, לא בעבר, ראשון–חמישי) — פרסום מתוזמן. image: { "option": "auto_select" } — ברירת מחדל, אנחנו בוחרים תמונה.
  • client_label — שם הלקוח שלכם (לסוכנויות), notes — הערות לכותב, team_notes — הערות לצוות BuyPost בלבד.
  • shared_with ("בשיתוף עם") — חובה באתרים שמסומנים במחירון requires_shared_fields. shared_company_id (ח.פ) — רשות.
  • image עם תמונות שלכם: { "option": "upload", "images": [{ "url": "https://…", "credit": "יח"צ" }] } — עד 2 תמונות, קישור או קובץ (file_base64 + filename, jpg/png/webp עד 5MB), וקרדיט צילום חובה לכל תמונה. קישור לתמונה מוכנה: { "option": "stock", "url": "https://…" }.
  • pixel — פיקסל מעקב, רק באתרים שמציעים (pixel_option): { "url": "https://…" } או קובץ. פיקסל בתשלום מתווסף למחיר.
  • redeem_later: true (+ quantity עד 20) — מימוש עתידי: קונים עכשיו עם website_id בלבד, ושולחים פרטים אחרי התשלום ב-redeem.
  • תאריך פרסום — ראשון עד חמישי בלבד. כתבה מוכנה (html/docx) — מילת מפתח וקישור רשות, אבל תמיד יחד.
  • המחירון והצעת המחיר מחזירים לכל אתר את כללי הכתיבה והפרסום שלו (writing_notes, publishing_restrictions) — הכותב שלנו פועל לפיהם. כל מחיר מסביר מאיפה הוא: מבצע / מחיר מיוחד / מחירון, וההנחה הקבועה שלכם.
  • קופונים: הקופונים האישיים שלכם מוחלים אוטומטית, באותם כללים כמו בסל באתר. לקוד מסוים — coupon_code; בלי קופונים אוטומטיים — apply_coupons: false. הצעת המחיר מראה אילו קופונים חלו וכמה הם חוסכים. הקופון מנוצל רק כשההזמנה משולמת; אם נוצל בינתיים במקום אחר, הסכום מתעדכן לפני התשלום.
  • בשגיאת פרטים ההודעה מפרטת מה חסר בכל כתבה, ו-details[].errors[].field אומר איזה שדה לתקן.
  • אין לפרסם תכנים בנושאי הימורים, טבק/עישון, תכנים מיניים או שירותי ליווי.

סטטוסים

pending ממתין — לתשלום (payment_status) או לאישור הנושא על ידי הצוות
topic_approved / writing הכנת תוכן
admin_review בבדיקת הצוות
review ממתין לאישור שלכם (approve / request_fix)
approved אושר — לפני שליחה לאתר
awaiting_image_approval נדרש אישור תמונה (נשלח במייל)
sent_to_publisher נשלח לאתר
draft_review / publisher_draft_review טיוטה באתר ממתינה לאישורכם — באתר BuyPost
published פורסם — published_url
rejected נדחה — זיכוי לפי התקנון

מצב התשלום של כל כתבה: payment_status = awaiting_payment / paid / cancelled. הזמנה שלא שולמה לא נכתבת, לא נשלחת לאתר ולא מתפרסמת. awaiting_redemption: true = נקנתה ושולמה ומחכה לפרטים שלכם (redeem). waiting_for_you: true = ממתינה לאישור שלכם (ונשלחת הודעת article.waiting_for_approval); השדה available_actions אומר אילו פעולות אפשריות עכשיו — טיוטה באתר המפרסם מאשרים באתר BuyPost. לכל כתבה יש progress: שלב, תיאור בעברית, על מי היא ממתינה ומה הצעד הבא; כתבה שפורסמה — published_url ו-published_at.

עדכונים לשרת שלכם (webhook)

מגדירים כתובת בעמוד API באזור האישי. בכל שינוי סטטוס של כתבה נשלחת בקשת POST. סוגים: article.waiting_for_approval, article.published, article.rejected, article.status_changed, order.paid (הזמנת API שולמה באתר והכתבות נכנסו לעבודה), credits.added (נוספו קרדיטים — קראו list_redeemable). כל הודעה חתומה — ודאו את החתימה:

// Node.js — אימות הודעת webhook
import crypto from 'node:crypto';

function isFromBuyPost(rawBody, headers, secret) {
  const ts = headers['x-buypost-timestamp'];
  const sig = (headers['x-buypost-signature'] || '').replace('sha256=', '');
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // older than 5 minutes
  const expected = crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  return sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

ענו בקוד 2xx תוך 5 שניות. הודעה שלא התקבלה נשלחת פעם נוספת; כל המשלוחים מופיעים ביומן בעמוד API.

שגיאות

401 missing_or_malformed_key / invalid_key מפתח חסר, שגוי או מבוטל
403 api_not_enabled הגישה ל-API לא אושרה לחשבון
403 site_only פעולה שנעשית רק באתר: תשלום, קניית קרדיטים, הגדרת webhook
409 not_waiting_for_approval / not_cancellable / not_editable הכתבה לא בשלב שמאפשר את הפעולה — ההודעה מסבירה מתי כן
422 validation_failed פרטי כתבה לא תקינים — details מפרט לכל כתבה (index) את הבעיות. לא נוצרה הזמנה
422 billing_profile_incomplete חסרים שם וטלפון בפרופיל — יש להשלים פעם אחת באתר
404 order_not_found / item_not_found ההזמנה או הכתבה לא קיימות או שאינן של החשבון
409 order_not_paid / redeem_details_required / redeem_after_payment שינוי כתבה של הזמנת אתר שלא שולמה; תאריך בלי פרטי כתבה לכתבה שלא מומשה; מימוש עתידי לפני התשלום
400 note_required / reason_required / changes_missing / item_ids_missing חסר שדה בבקשה — ההודעה אומרת איזה
422 scheduled_date_invalid / scheduled_date_weekend תאריך פרסום בעבר, בפורמט לא נכון, או בשישי / שבת
422 coupon_not_found / coupon_unusable / coupon_min_order / coupon_not_combinable / coupon_not_applicable קוד הקופון לא נמצא, לא בתוקף, מתחת למינימום, לא משתלב עם הנחה קבועה, או לא חל על הכתבות
409 coupon_changed הקופון נוצל או פג לפני התשלום — הסכום עודכן, אשרו שוב
409 busy_try_again פעולה אחרת של החשבון מתבצעת — נסו שוב בעוד כמה שניות
429 rate_limited / daily_request_limit יותר מ-10 בקשות בדקה, או חריגה ממכסת הבקשות היומית (300 לחשבון)
429 daily_article_limit / too_many_unpaid_orders חריגה ממכסת הכתבות היומית, או יותר מדי הזמנות שמחכות לתשלום
429 too_many_bad_keys יותר מדי ניסיונות עם מפתח שגוי מאותה כתובת — חסימה ל-10 דקות
500 internal_error / order_failed שגיאה אצלנו — נסו שוב (עם אותו idempotency_key, בלי חשש לכפילות)