API — שליחת הודעות ואוטומציה
REST API אחד לשליחת הודעות וואטסאפ, ניהול אנשי קשר וקריאת שיחות. מיועד לחיבור מ-Make, Zapier, n8n או מהשרת שלכם.
כבר יש לכם חשבון? הגרסה של העמוד הזה בתוך המערכת מציגה את אותו תיעוד עם מזהה הערוץ ושמות התבניות האמיתיים שלכם, מוכנים להעתקה. אין עדיין חשבון? דברו איתנו.
לפני שמתחילים
אימות
כל קריאה נושאת מפתח API בכותרת Authorization. מפתח נוצר בהגדרות → מפתחות API, ומוצג פעם אחת בלבד — אצלנו נשמר רק ה-hash שלו, כך שאין דרך לשחזר אותו אחר כך. כל המפתחות מתחילים ב-qsk_.
Authorization: Bearer qsk_xxx Content-Type: application/json
כתובת הבסיס: https://quick-chat.app · כל התשובות הן JSON · מפתח נושא הרשאות read ו/או write, וכל אנדפוינט למטה מציין מה הוא דורש.
חלון 24 השעות — הכלל שקובע הכל
זו מגבלה של Meta, לא שלנו, והיא המקור לרוב התקלות באינטגרציה ראשונה. מרגע שלקוח שולח לכם הודעה נפתח חלון של 24 שעות שבו אפשר להשיב לו בטקסט חופשי, בחינם. אחרי שהחלון נסגר — ולקוח שהשאיר פרטים בקמפיין ומעולם לא כתב לכם הוא מחוץ לחלון מלכתחילה — הדרך היחידה להגיע אליו היא תבנית מאושרת, והיא בתשלום.
אין צורך לממש את הלוגיקה הזו אצלכם: POST /api/v1/send מקבל גם טקסט וגם תבנית בבקשה אחת ובוחר לבד לפי מצב החלון, ומחזיר mode ו-billable כדי שתדעו מה קרה בפועל.
idempotencyKey — אל תדלגו על זה
Make, Zapier ו-n8n מבצעים ניסיון חוזר אוטומטי כשבקשה חוזרת ב-timeout. בלי מפתח ייחודי לכל שליחה, ניסיון חוזר כזה שולח ללקוח את אותה הודעה פעמיים — ומחייב אתכם פעמיים. השתמשו במזהה יציב מהמערכת שלכם, למשל lead-8832 או order-1234-ready. בקשה חוזרת עם אותו מפתח מחזירה duplicate: true ולא שולחת דבר.
שליחת הודעות
הלב של ה-API. אם המטרה שלכם היא "לקוח משאיר פרטים → מקבל וואטסאפ", האנדפוינט הראשון ברשימה הוא כל מה שצריך.
שליחה חכמה — בחרו לי איך
שולחים טלפון + טקסט + תבנית בבקשה אחת, ואנחנו בוחרים לפי מצב חלון 24 השעות: חלון פתוח → טקסט חופשי (חינם), חלון סגור → תבנית מאושרת (בתשלום). התשובה תמיד אומרת מה נשלח בפועל ואם זה חויב.
שדות ב-body
phonestringחובהמספר הנמען. מקבל פורמט ישראלי מקומי (0501234567) או E.164 (+972501234567).
textstringטקסט חופשי, עד 8000 תווים. נשלח רק אם חלון 24 השעות פתוח. נדרש אחד מבין text / template.
templateobjectתבנית מאושרת: { name, language (ברירת מחדל "he"), variables: string[], buttons?: [{ index, subType, value }] }. זו הדרך היחידה להגיע ללקוח מחוץ לחלון.
mode"auto" | "template"ברירת מחדל auto — בוחר לפי מצב החלון. "template" כופה תבנית גם בתוך החלון, שימושי כשהכפתורים של התבנית הם העיקר ולא רק היכולת לפתוח שיחה.
idempotencyKeystringמפתח למניעת כפילות. חובה בפועל בכל תרחיש Make/Zapier — הם עושים retry אוטומטי על timeout, ובלי המפתח הלקוח יקבל את ההודעה פעמיים ותשלמו פעמיים.
contactNamestringשם לאיש הקשר. בשימוש רק אם הקריאה הזו יוצרת אותו.
channelIdstringנדרש רק אם לארגון מחובר יותר מערוץ WhatsApp רשמי אחד. אחרת נבחר הערוץ היחיד.
curl -X POST https://quick-chat.app/api/v1/send \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "0501234567",
"contactName": "דנה לוי",
"text": "היי דנה, קיבלנו את הפרטים שלך!",
"template": {
"name": "your_template_name",
"language": "he",
"variables": ["דנה"]
},
"idempotencyKey": "lead-8832"
}'{
"ok": true,
"mode": "template",
"billable": true,
"duplicate": false,
"conversationId": "conv_...",
"contactId": "cnt_...",
"messageId": "msg_...",
"conversationCreated": true,
"window": {
"open": false,
"lastInboundAt": null,
"expiresAt": null
}
}- •שלחתם רק `text` והחלון סגור? תקבלו 409 עם code `window_closed` שמציין במפורש להוסיף `template`. מי שלא רוצה לשלם לעולם יכול להסתמך על ההתנהגות הזו.
- •`billable: true` מציין שההודעה חויבה על ידי Meta. `duplicate: true` אומר שה-idempotencyKey תפס בקשה חוזרת — לא נשלחה הודעה ולא חויבתם.
- •איש הקשר והשיחה נוצרים אוטומטית אם אינם קיימים, וההודעה מופיעה ב-Inbox כמו כל שיחה אחרת.
שליחת תבנית מאושרת
שולח תמיד תבנית, בלי לבדוק את מצב החלון. מתאים כשאתם יודעים בוודאות שאתם פונים ללקוח קר. אם אתם בונים תרחיש חדש — עדיף /api/v1/send.
שדות ב-body
phonestringחובהמספר הנמען.
namestringחובהשם התבנית בדיוק כפי שאושרה ב-WABA.
languagestringקוד שפה, ברירת מחדל "he".
variablesstring[]ערכים ל-{{1}}, {{2}}… לפי הסדר. עד 10.
buttonsobject[]ערכים לכפתורים דינמיים: [{ index, subType: "url" | "quick_reply", value }]. עד 3.
idempotencyKeystringמפתח למניעת כפילות, בדיוק כמו ב-/api/v1/send.
contactName / channelIdstringכמו ב-/api/v1/send.
curl -X POST https://quick-chat.app/api/v1/messages/template \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "0501234567",
"name": "your_template_name",
"language": "he",
"variables": ["דנה", "פיצה משפחתית"],
"idempotencyKey": "order-1234-ready"
}'{
"ok": true,
"duplicate": false,
"billable": true,
"conversationId": "conv_...",
"contactId": "cnt_...",
"messageId": "msg_...",
"status": "SENT",
"conversationCreated": true
}- •האנדפוינט הזה במכוון לא בודק את חלון 24 השעות — תבנית היא הדרך היחידה שMeta מתירה להגיע מחוצה לו, ולכן אין מה לבדוק.
טקסט חופשי או קובץ
שתי דרכי פנייה: `conversationId` כדי להשיב בתוך שיחה קיימת, או `phone` כדי לפנות לאדם. טקסט חופשי עובר רק בתוך חלון 24 השעות.
שדות ב-body
conversationIdstringמזהה שיחה קיימת. חובה בדיוק אחד מבין conversationId / phone.
phonestringפנייה לפי מספר — מאתר או יוצר איש קשר ושיחה.
textstringעד 8000 תווים. נדרש text או attachment.
attachmentobject{ url, mime, filename?, size? } — קובץ בכתובת ציבורית.
contactName / channelIdstringבשימוש רק יחד עם phone.
curl -X POST https://quick-chat.app/api/v1/messages \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{
"conversationId": "conv_xxxxxxxx",
"text": "בדקנו — ההזמנה יוצאת היום"
}'{
"ok": true,
"messageId": "msg_..."
}- •פנייה לפי `phone` כשהחלון סגור מחזירה 409 עם code `window_closed` ומפנה ל-/api/v1/messages/template. כישלון רועש עדיף על הודעה שנעלמת בשקט באמצע אוטומציה.
רשימת התבניות המאושרות
מחזיר את התבניות שעל ה-WABA של הארגון, כולל מספר המשתנים והכפתורים של כל אחת — כדי שתרחיש חיצוני יוכל לבחור תבנית בלי להיכנס ל-WhatsApp Manager.
פרמטרים ב-query
channelIdstringנדרש רק אם מחוברים כמה ערוצי WhatsApp רשמיים.
statusstringסינון, למשל APPROVED.
curl "https://quick-chat.app/api/v1/templates?status=APPROVED" \ -H "Authorization: Bearer qsk_xxx"
{
"channelId": "chn_...",
"templates": [
{
"name": "order_ready",
"language": "he",
"status": "APPROVED",
"category": "UTILITY",
"body": "היי {{1}}, ההזמנה {{2}} מוכנה",
"variableCount": 2,
"buttons": [
{ "index": 0, "type": "URL", "text": "למעקב", "dynamic": true }
]
}
]
}- •`variableCount` הוא בדיוק האורך שצריך להיות ל-`variables` בשליחה. `dynamic: true` על כפתור אומר שחייבים לספק לו value.
אנשי קשר
יצירה, עדכון ותיוג — כדי שהליד מהקמפיין ייכנס למערכת עם התגיות הנכונות.
יצירה או עדכון (upsert)
מוסיף איש קשר, או מעדכן קיים. הדדופ הוא לפי טלפון ואז לפי אימייל — בדיוק כמו בייבוא CSV מהממשק.
שדות ב-body
namestringשם מלא.
phonestringמספר טלפון.
emailstringכתובת אימייל.
tagsstring[]עד 20 תגיות. דורס את הרשימה הקיימת.
curl -X POST https://quick-chat.app/api/v1/contacts \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{"name":"דנה לוי","phone":"+972501234567","tags":["ליד קמפיין"]}'{
"contact": {
"id": "cnt_...",
"name": "דנה לוי",
"primaryPhone": "+972501234567",
"primaryEmail": null,
"tags": ["ליד קמפיין"]
},
"created": true
}- •נדרש לפחות אחד מבין phone / email / name. יצירה מחזירה 201, עדכון מחזיר 200.
- •`tags` כאן דורס. כדי להוסיף תגית בלי למחוק קיימות — /api/v1/contacts/tag.
הוספה והסרה של תגיות
מוסיף או מסיר תגיות לאיש קשר לפי טלפון, אימייל או מזהה. תגית חדשה נרשמת גם ברשימת התגיות של הארגון כדי שתופיע בפילטרים של ה-Inbox.
שדות ב-body
phone / email / contactIdstringחובהנדרש אחד מהם לאיתור איש הקשר.
addstring[]תגיות להוספה, עד 20. נדרש add או remove.
removestring[]תגיות להסרה.
namestringשם, בשימוש רק אם הקריאה יוצרת את איש הקשר.
curl -X POST https://quick-chat.app/api/v1/contacts/tag \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{"phone":"0501234567","add":["ליד חם"],"remove":["ליד קר"]}'{
"ok": true,
"contactId": "cnt_...",
"tags": ["ליד חם"],
"created": false
}- •איש קשר חדש נוצר דרך פותר הזהויות, כדי לא לפצל אדם שכבר מוכר לנו מערוץ אחר. לכן נדרש לפחות ערוץ מחובר אחד בארגון.
- •`contactId` שלא נמצא מחזיר 404 — לא ניצור איש קשר תחת מזהה מומצא.
רשימת אנשי קשר
עימוד לפי cursor על תאריך היצירה, מהחדש לישן.
פרמטרים ב-query
limitnumberברירת מחדל 50, מקסימום 100.
cursorstringה-createdAt של הפריט האחרון בעמוד הקודם (ISO-8601).
curl "https://quick-chat.app/api/v1/contacts?limit=50" \ -H "Authorization: Bearer qsk_xxx"
{
"items": [ { "id": "cnt_...", "name": "דנה לוי", "primaryPhone": "+9725...", "tags": [] } ],
"nextCursor": "2026-09-20T10:11:12.000Z"
}- •`nextCursor: null` מציין שהגעתם לעמוד האחרון.
שיחות וחשבון
קריאה בלבד — למשיכת מצב למערכת שלכם ולבדיקת מכסות לפני ריצה גדולה.
רשימת שיחות
עימוד לפי lastMessageAt, עם סינון לפי סטטוס ומשויך.
פרמטרים ב-query
statusstringOPEN | PENDING | RESOLVED | SNOOZED.
assignedToUserIdstringרשימה מופרדת בפסיקים, או "null" לשיחות לא משויכות.
limit / cursornumber / stringברירת מחדל 50, מקסימום 100. ה-cursor הוא lastMessageAt.
curl "https://quick-chat.app/api/v1/conversations?status=OPEN&limit=20" \ -H "Authorization: Bearer qsk_xxx"
{
"items": [
{
"id": "conv_...",
"status": "OPEN",
"contactId": "cnt_...",
"channelId": "chn_...",
"assignedToUserId": null,
"lastMessageAt": "2026-09-22T08:00:00.000Z",
"lastInboundAt": "2026-09-22T08:00:00.000Z",
"firstResponseSeconds": 42,
"unreadCount": 1
}
],
"nextCursor": null
}בדיקת מפתח ומכסות
מאמת את המפתח ומחזיר כמה קריאות ותבניות נשארו לכם. הקריאה הזו לא צורכת מהמכסה — תרחיש שבודק את המכסה של עצמו לא אמור להיות זה שמחסל אותה.
curl https://quick-chat.app/api/v1/me \ -H "Authorization: Bearer qsk_xxx"
{
"organizationId": "org_...",
"organizationName": "קוויק פוד",
"scopes": ["read", "write"],
"apiKeyId": "key_...",
"limits": {
"apiRequests": { "limit": 120, "used": 3, "remaining": 117, "window": "minute", "resetAt": "..." },
"templateSends": { "limit": 125, "used": 40, "remaining": 85, "window": "day", "resetAt": "..." }
}
}- •קראו לזה פעם אחת לפני לולאה על מאות נמענים — עדיף לגלות שנגמרה המכסה מראש מאשר מ-429 באמצע.
מגבלות קצב
- 120 קריאות API לדקה לארגון. חריגה מחזירה 429 עם כותרת
retry-after. - 125 שליחות תבנית ליום לארגון. המספר מכוון בכוונה מתחת לתקרה ההתחלתית של Meta (250 שיחות יזומות ב-24 שעות): עדיף שאוטומציה שיצאה משליטה תיתקל במונה שלנו, שמחזיר 429 ולא עולה כלום, מאשר בתקרה של Meta — שם כל הודעה שעברה כבר חויבה וגם פוגעת בדירוג האיכות של המספר.
GET /api/v1/meאינו נספר במכסה, כדי שבדיקת מכסה לא תהיה הדבר שמכלה אותה.- שתי המגבלות ניתנות להעלאה פר ארגון. אם הנפח האמיתי שלכם גדול יותר — פנו אלינו ונעלה אותן לפני הקמפיין, לא באמצעו.
קודי שגיאה
כל שגיאה מחזירה { error, code? } — השדה error הוא טקסט בעברית שאפשר להציג למשתמש, ו-code הוא המזהה היציב שכדאי לבנות עליו לוגיקה.
- 401
הכותרת Authorization חסרה, לא בפורמט Bearer, או שהמפתח בוטל / פג.
מה עושים: ודאו `Authorization: Bearer qsk_...`. מפתח שבוטל מפסיק לעבוד תוך דקה לכל היותר.
- 403
למפתח אין את ה-scope הנדרש (read או write).
מה עושים: צרו מפתח חדש עם ההרשאות הנכונות.
- 400
invalid_bodyגוף הבקשה לא עבר ולידציה. השדה `issues` מפרט בדיוק מה נכשל.
מה עושים: קראו את `issues` — הוא מציין את שם השדה והציפייה.
- 400
invalid_phoneהמספר לא ניתן לנרמול.
מה עושים: שלחו 0501234567 או +972501234567.
- 400
no_channelאין בארגון ערוץ WhatsApp רשמי מחובר.
מה עושים: חברו ערוץ בהגדרות → ערוצים.
- 400
ambiguous_channelמחוברים כמה ערוצי WhatsApp והבקשה לא ציינה באיזה להשתמש.
מה עושים: הוסיפו `channelId`. התשובה כוללת את רשימת הערוצים לבחירה.
- 404
channel_not_foundה-channelId לא קיים בארגון, או שאינו ערוץ WhatsApp.
מה עושים: בדקו את המזהה מול רשימת הערוצים.
- 409
window_closedחלון 24 השעות סגור וניסיתם לשלוח טקסט חופשי. Meta הייתה דוחה את ההודעה ממילא.
מה עושים: הוסיפו `template` לבקשה, או עברו ל-/api/v1/messages/template.
- 409
channel_disconnectedהערוץ קיים אבל אינו מחובר כרגע.
מה עושים: בדקו את הערוץ בהגדרות — בדרך כלל טוקן שפג.
- 409
channel_incompleteלערוץ חסר WABA ID או טוקן.
מה עושים: חברו את הערוץ מחדש.
- 429
rate_limitedחריגה ממגבלת הקצב. התשובה כוללת `limit` ו-`resetAt`, וכן כותרות retry-after ו-x-ratelimit-*.
מה עושים: המתינו לפי `retry-after`. אם המכסה היומית לתבניות קטנה מדי לנפח שלכם — נעלה אותה לארגון.
- 502
send_failedMeta דחתה את השליחה. השגיאה כוללת את הסיבה שהתקבלה מהם.
מה עושים: ברוב המקרים: תבנית שלא אושרה, שם שגוי, או מספר משתנים שאינו תואם.
מתכון: ליד מקמפיין → הודעת וואטסאפ
- הכינו תבנית. בהגדרות → ערוצים → תבניות, צרו תבנית בקטגוריית שיווק עם המשתנים שאתם צריכים ושלחו לאישור Meta. בדרך כלל דקות עד שעות.
- צרו מפתח API בהגדרות → מפתחות API והעתיקו אותו — הוא מוצג פעם אחת.
- חברו את הטופס. בטופס הלידים שלכם, או במודול HTTP של Make, הוסיפו קריאת POST אחת:
curl -X POST https://quick-chat.app/api/v1/send \
-H "Authorization: Bearer qsk_xxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "{{ lead.phone }}",
"contactName": "{{ lead.name }}",
"template": {
"name": "your_template_name",
"language": "he",
"variables": ["{{ lead.name }}"]
},
"idempotencyKey": "lead-{{ lead.id }}"
}'- תייגו את הליד (אופציונלי) בקריאה שנייה ל-
/api/v1/contacts/tag, כדי שהוא יופיע בפילטר של ה-Inbox לפי הקמפיין שממנו הגיע. - זהו. כשהלקוח יענה, התשובה תיכנס ל-Inbox כשיחה רגילה, החלון ייפתח, והצוות יוכל להמשיך משם בטקסט חופשי בלי עלות נוספת.
שאלה שלא מכוסה כאן?
כתבו לנו ל-support@quick-chat.app. אם אתם עדיין מתלבטים בין חיבור רשמי ל-Coexistence, המדריך WhatsApp Business API מסביר את ההבדל.