{"id":279754,"date":"2026-08-13T15:44:48","date_gmt":"2026-08-13T13:44:48","guid":{"rendered":"https:\/\/www.unipile.com\/?p=279754"},"modified":"2026-08-13T15:48:44","modified_gmt":"2026-08-13T13:48:44","slug":"whatsapp-api-php","status":"publish","type":"post","link":"https:\/\/www.unipile.com\/fr\/whatsapp-api-php\/","title":{"rendered":"WhatsApp API with PHP: The Complete Integration Guide"},"content":{"rendered":"\n[et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; global_colors_info=&#8221;{}&#8221;][et_pb_row _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; global_colors_info=&#8221;{}&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221;]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<style>\n#unipile-toc,\n#unipile-toc *,\n#unipile-toc *::before,\n#unipile-toc *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#unipile-toc br { display: none !important; }\n#unipile-toc p { display: contents !important; }\n#unipile-toc {\n  all: initial !important;\n  display: block !important;\n  max-width: 1100px !important;\n  margin: 0 auto !important;\n  padding: 0 !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n}\n#unipile-toc .utc-card {\n  background: #ffffff !important;\n  border-radius: 16px !important;\n  border: 1px solid #e5e7eb !important;\n  padding: 32px !important;\n  box-shadow: 0 2px 12px rgba(15, 39, 54, 0.04) !important;\n}\n#unipile-toc .utc-header {\n  display: flex !important;\n  align-items: center !important;\n  justify-content: space-between !important;\n  gap: 12px !important;\n  margin-bottom: 24px !important;\n  padding-bottom: 20px !important;\n  border-bottom: 1px solid #e5e7eb !important;\n}\n#unipile-toc .utc-header-left {\n  display: flex !important;\n  align-items: center !important;\n  gap: 12px !important;\n}\n#unipile-toc .utc-icon-box {\n  width: 36px !important;\n  height: 36px !important;\n  background: rgba(59, 185, 139, 0.12) !important;\n  border-radius: 8px !important;\n  display: flex !important;\n  align-items: center !important;\n  justify-content: center !important;\n  flex-shrink: 0 !important;\n}\n#unipile-toc .utc-icon-box svg {\n  width: 18px !important;\n  height: 18px !important;\n  stroke: #3BB98B !important;\n  fill: none !important;\n  stroke-width: 2.2 !important;\n  stroke-linecap: round !important;\n  stroke-linejoin: round !important;\n}\n#unipile-toc .utc-title {\n  font-family: 'Poppins', sans-serif !important;\n  font-size: 15px !important;\n  font-weight: 700 !important;\n  color: #0f2736 !important;\n  text-transform: uppercase !important;\n  letter-spacing: 0.5px !important;\n}\n#unipile-toc .utc-toggle {\n  display: none !important;\n  align-items: center !important;\n  gap: 6px !important;\n  background: transparent !important;\n  cursor: pointer !important;\n  font-size: 13px !important;\n  font-weight: 600 !important;\n  color: #3BB98B !important;\n  padding: 6px 10px !important;\n  border-radius: 6px !important;\n  transition: background 0.2s ease !important;\n}\n#unipile-toc .utc-toggle svg {\n  width: 14px !important;\n  height: 14px !important;\n  stroke: #3BB98B !important;\n  fill: none !important;\n  stroke-width: 2.5 !important;\n  stroke-linecap: round !important;\n  stroke-linejoin: round !important;\n  transition: transform 0.3s ease !important;\n}\n#unipile-toc.utc-collapsed .utc-toggle svg {\n  transform: rotate(-90deg) !important;\n}\n#unipile-toc .utc-grid {\n  display: grid !important;\n  grid-template-columns: repeat(4, 1fr) !important;\n  gap: 0 !important;\n}\n#unipile-toc .utc-col {\n  padding: 0 24px !important;\n  border-left: 1px solid #e5e7eb !important;\n}\n#unipile-toc .utc-col:first-child {\n  padding-left: 0 !important;\n  border-left: none !important;\n}\n#unipile-toc .utc-col:last-child {\n  padding-right: 0 !important;\n}\n#unipile-toc .utc-col-label {\n  font-size: 11px !important;\n  font-weight: 700 !important;\n  color: #94a3b8 !important;\n  text-transform: uppercase !important;\n  letter-spacing: 0.8px !important;\n  margin-bottom: 14px !important;\n  display: block !important;\n}\n#unipile-toc .utc-link-list {\n  display: flex !important;\n  flex-direction: column !important;\n  gap: 10px !important;\n}\n#unipile-toc .utc-link {\n  display: flex !important;\n  align-items: flex-start !important;\n  gap: 10px !important;\n  cursor: pointer !important;\n  transition: all 0.2s ease !important;\n  text-decoration: none !important;\n  padding: 4px 0 !important;\n}\n#unipile-toc .utc-num {\n  width: 18px !important;\n  height: 18px !important;\n  flex-shrink: 0 !important;\n  background: #f4f5f7 !important;\n  border-radius: 4px !important;\n  display: flex !important;\n  align-items: center !important;\n  justify-content: center !important;\n  font-size: 10px !important;\n  font-weight: 700 !important;\n  color: #94a3b8 !important;\n  transition: all 0.2s ease !important;\n  margin-top: 1px !important;\n}\n#unipile-toc .utc-num.utc-num-faq {\n  font-size: 8px !important;\n  letter-spacing: 0.2px !important;\n}\n#unipile-toc .utc-link-text {\n  font-size: 13px !important;\n  font-weight: 500 !important;\n  color: #383838 !important;\n  line-height: 1.45 !important;\n  transition: color 0.2s ease !important;\n  flex: 1 !important;\n}\n#unipile-toc .utc-link:hover .utc-num {\n  background: rgba(59, 185, 139, 0.15) !important;\n  color: #3BB98B !important;\n}\n#unipile-toc .utc-link:hover .utc-link-text {\n  color: #0f2736 !important;\n}\n#unipile-toc .utc-link.utc-active .utc-num {\n  background: #3BB98B !important;\n  color: #ffffff !important;\n}\n#unipile-toc .utc-link.utc-active .utc-link-text {\n  color: #0f2736 !important;\n  font-weight: 600 !important;\n}\n#unipile-toc .utc-link.utc-read .utc-num {\n  background: rgba(59, 185, 139, 0.15) !important;\n  color: #3BB98B !important;\n}\n#unipile-toc .utc-tag-best {\n  display: inline-block !important;\n  font-size: 9px !important;\n  font-weight: 700 !important;\n  color: #ffffff !important;\n  background: #3BB98B !important;\n  padding: 2px 6px !important;\n  border-radius: 4px !important;\n  text-transform: uppercase !important;\n  letter-spacing: 0.5px !important;\n  margin-left: 6px !important;\n  vertical-align: middle !important;\n}\n@media (max-width: 1000px) {\n  #unipile-toc .utc-grid {\n    grid-template-columns: repeat(2, 1fr) !important;\n    gap: 24px 0 !important;\n  }\n  #unipile-toc .utc-col {\n    padding: 0 20px !important;\n  }\n  #unipile-toc .utc-col:nth-child(2n+1) {\n    padding-left: 0 !important;\n    border-left: none !important;\n  }\n  #unipile-toc .utc-col:nth-child(2n) {\n    padding-right: 0 !important;\n  }\n}\n@media (max-width: 700px) {\n  #unipile-toc .utc-card {\n    padding: 22px !important;\n  }\n  #unipile-toc .utc-header {\n    margin-bottom: 0 !important;\n    padding-bottom: 0 !important;\n    border-bottom: none !important;\n  }\n  #unipile-toc .utc-toggle {\n    display: flex !important;\n  }\n  #unipile-toc .utc-grid {\n    grid-template-columns: 1fr !important;\n    gap: 22px !important;\n    max-height: 2000px !important;\n    overflow: hidden !important;\n    transition: max-height 0.4s ease, margin-top 0.3s ease, padding-top 0.3s ease !important;\n    margin-top: 22px !important;\n    padding-top: 22px !important;\n    border-top: 1px solid #e5e7eb !important;\n  }\n  #unipile-toc.utc-collapsed .utc-grid {\n    max-height: 0 !important;\n    margin-top: 0 !important;\n    padding-top: 0 !important;\n    border-top: none !important;\n  }\n  #unipile-toc .utc-col {\n    padding: 0 !important;\n    border-left: none !important;\n    border-top: 1px solid #e5e7eb !important;\n    padding-top: 18px !important;\n  }\n  #unipile-toc .utc-col:first-child {\n    border-top: none !important;\n    padding-top: 0 !important;\n  }\n}\n<\/style>\n<div id=\"unipile-toc\">\n  <div class=\"utc-card\">\n    <div class=\"utc-header\">\n      <div class=\"utc-header-left\">\n        <div class=\"utc-icon-box\">\n          <svg viewBox=\"0 0 24 24\">\n            <line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"\/>\n            <line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"\/>\n            <line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"\/>\n            <line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"\/>\n            <line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"\/>\n            <line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"\/>\n          <\/svg>\n        <\/div>\n        <span class=\"utc-title\">Table of Contents<\/span>\n      <\/div>\n      <button type=\"button\" class=\"utc-toggle\" aria-label=\"Toggle table of contents\">\n        <span class=\"utc-toggle-label\">Hide<\/span>\n        <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n      <\/button>\n    <\/div>\n<div class=\"utc-grid\">\n      <div class=\"utc-col\">\n        <span class=\"utc-col-label\">Fundamentals<\/span>\n        <div class=\"utc-link-list\">\n          <a class=\"utc-link\" href=\"#wpp-what\">\n            <span class=\"utc-num\">01<\/span>\n            <span class=\"utc-link-text\">What is the WhatsApp API in PHP?<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-which\">\n            <span class=\"utc-num\">02<\/span>\n            <span class=\"utc-link-text\">Which WhatsApp API should you use?<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-prereq\">\n            <span class=\"utc-num\">03<\/span>\n            <span class=\"utc-link-text\">What you need before writing code<\/span>\n          <\/a>\n        <\/div>\n      <\/div>\n<div class=\"utc-col\">\n        <span class=\"utc-col-label\">Connect &amp; Send<\/span>\n        <div class=\"utc-link-list\">\n          <a class=\"utc-link\" href=\"#wpp-connect\">\n            <span class=\"utc-num\">04<\/span>\n            <span class=\"utc-link-text\">Connect a WhatsApp account<span class=\"utc-tag-best\">Best<\/span><\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-send\">\n            <span class=\"utc-num\">05<\/span>\n            <span class=\"utc-link-text\">Send a message with Guzzle<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-start\">\n            <span class=\"utc-num\">06<\/span>\n            <span class=\"utc-link-text\">Start a new conversation<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-retrieve\">\n            <span class=\"utc-num\">07<\/span>\n            <span class=\"utc-link-text\">Retrieve chats and messages<\/span>\n          <\/a>\n        <\/div>\n      <\/div>\n<div class=\"utc-col\">\n        <span class=\"utc-col-label\">Production<\/span>\n        <div class=\"utc-link-list\">\n          <a class=\"utc-link\" href=\"#wpp-webhook\">\n            <span class=\"utc-num\">08<\/span>\n            <span class=\"utc-link-text\">Receive messages with a webhook<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-laravel\">\n            <span class=\"utc-num\">09<\/span>\n            <span class=\"utc-link-text\">Integrate into a Laravel app<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-groups\">\n            <span class=\"utc-num\">10<\/span>\n            <span class=\"utc-link-text\">Manage WhatsApp groups<\/span>\n          <\/a>\n        <\/div>\n      <\/div>\n<div class=\"utc-col\">\n        <span class=\"utc-col-label\">Scale, Cost &amp; FAQ<\/span>\n        <div class=\"utc-link-list\">\n          <a class=\"utc-link\" href=\"#wpp-tenant\">\n            <span class=\"utc-num\">11<\/span>\n            <span class=\"utc-link-text\">Handle many user accounts<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-mistakes\">\n            <span class=\"utc-num\">12<\/span>\n            <span class=\"utc-link-text\">Common PHP-specific mistakes<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-cost\">\n            <span class=\"utc-num\">13<\/span>\n            <span class=\"utc-link-text\">Cost per message<\/span>\n          <\/a>\n          <a class=\"utc-link\" href=\"#wpp-faq\">\n            <span class=\"utc-num utc-num-faq\">FAQ<\/span>\n            <span class=\"utc-link-text\">Frequently Asked Questions<\/span>\n          <\/a>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  var toc = document.getElementById('unipile-toc');\n  if (!toc) return;\nvar toggleBtn = toc.querySelector('.utc-toggle');\n  var toggleLabel = toc.querySelector('.utc-toggle-label');\n  if (toggleBtn) {\n    toggleBtn.addEventListener('click', function(){\n      var isCollapsed = toc.classList.toggle('utc-collapsed');\n      if (toggleLabel) toggleLabel.textContent = isCollapsed ? 'Show' : 'Hide';\n    });\n    if (window.innerWidth <= 700) {\n      toc.classList.add('utc-collapsed');\n      if (toggleLabel) toggleLabel.textContent = 'Show';\n    }\n  }\nvar links = toc.querySelectorAll('.utc-link');\n  links.forEach(function(link){\n    link.addEventListener('click', function(e){\n      var href = link.getAttribute('href');\n      if (!href || href.charAt(0) !== '#') return;\n      var target = document.getElementById(href.substring(1));\n      if (target) {\n        e.preventDefault();\n        var offset = 80;\n        var top = target.getBoundingClientRect().top + window.pageYOffset - offset;\n        window.scrollTo({ top: top, behavior: 'smooth' });\n      }\n    });\n  });\nvar sectionIds = [];\n  links.forEach(function(link){\n    var href = link.getAttribute('href');\n    if (href &#038;&#038; href.charAt(0) === '#') sectionIds.push(href.substring(1));\n  });\nfunction updateActive(){\n    var scrollY = window.pageYOffset + 120;\n    var activeId = null;\n    var readIds = [];\n    sectionIds.forEach(function(id){\n      var el = document.getElementById(id);\n      if (el) {\n        var top = el.getBoundingClientRect().top + window.pageYOffset;\n        if (top <= scrollY) {\n          activeId = id;\n          readIds.push(id);\n        }\n      }\n    });\n    links.forEach(function(link){\n      var href = link.getAttribute('href');\n      var id = href ? href.substring(1) : '';\n      link.classList.remove('utc-active', 'utc-read');\n      if (id === activeId) {\n        link.classList.add('utc-active');\n      } else if (readIds.indexOf(id) !== -1) {\n        link.classList.add('utc-read');\n      }\n    });\n  }\nif ('IntersectionObserver' in window) {\n    var observer = new IntersectionObserver(function(){\n      updateActive();\n    }, { rootMargin: '-120px 0px -60% 0px' });\n    sectionIds.forEach(function(id){\n      var el = document.getElementById(id);\n      if (el) observer.observe(el);\n    });\n  }\n  window.addEventListener('scroll', updateActive, { passive: true });\n  updateActive();\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-hero-top\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-hero { background: transparent !important; }\n#upl-wpp-hero *, #upl-wpp-hero *::before, #upl-wpp-hero *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-hero br { display: none !important; }\n#upl-wpp-hero p { display: contents !important; }\n#upl-wpp-hero { padding: 56px 20px 64px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-hero .wph-container {\n  max-width: 1200px !important;\n  margin: 0 auto !important;\n  display: grid !important;\n  grid-template-columns: 1.05fr 0.95fr !important;\n  gap: 56px !important;\n  align-items: center !important;\n}\n#upl-wpp-hero .wph-badge {\n  display: inline-flex !important;\n  align-items: center !important;\n  gap: 8px !important;\n  background: rgba(59, 185, 139, 0.12) !important;\n  padding: 7px 14px !important;\n  border-radius: 20px !important;\n  margin-bottom: 22px !important;\n}\n#upl-wpp-hero .wph-badge-dot { width: 7px !important; height: 7px !important; border-radius: 50% !important; background: #3BB98B !important; flex-shrink: 0 !important; }\n#upl-wpp-hero .wph-badge span:not(.wph-badge-dot) { font-size: 12px !important; font-weight: 700 !important; color: #2aaa7e !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; }\n#upl-wpp-hero h1 {\n  font-family: 'Poppins', sans-serif !important;\n  font-size: 44px !important;\n  font-weight: 700 !important;\n  color: #0f2736 !important;\n  line-height: 1.18 !important;\n  margin-bottom: 22px !important;\n}\n#upl-wpp-hero h1 span { color: #3BB98B !important; }\n#upl-wpp-hero .wph-desc { font-size: 17px !important; line-height: 1.75 !important; color: #383838 !important; margin-bottom: 32px !important; }\n#upl-wpp-hero .wph-desc strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-hero .wph-desc code { font-family: 'Courier New', monospace !important; background: rgba(15,39,54,0.06) !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.92em !important; color: #0f2736 !important; }\n#upl-wpp-hero .wph-actions { display: flex !important; align-items: center !important; gap: 14px !important; flex-wrap: wrap !important; margin-bottom: 26px !important; }\n#upl-wpp-hero .wph-cta-primary {\n  display: inline-flex !important; align-items: center !important; gap: 8px !important;\n  background: #DDDF4C !important; color: #0f2736 !important;\n  padding: 14px 28px !important; border-radius: 8px !important;\n  font-size: 0.95rem !important; font-weight: 600 !important;\n  border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important;\n}\n#upl-wpp-hero .wph-cta-primary:hover { transform: translateY(-5px) !important; }\n#upl-wpp-hero .wph-cta-primary svg { width: 16px !important; height: 16px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-hero .wph-cta-secondary {\n  display: inline-flex !important; align-items: center !important; gap: 8px !important;\n  background: transparent !important; color: #0f2736 !important;\n  padding: 12px 24px !important; border-radius: 8px !important;\n  font-size: 0.95rem !important; font-weight: 600 !important;\n  border: 2px solid #0f2736 !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important;\n}\n#upl-wpp-hero .wph-cta-secondary:hover { background: #0f2736 !important; color: #ffffff !important; }\n#upl-wpp-hero .wph-trust { display: flex !important; align-items: center !important; gap: 18px !important; flex-wrap: wrap !important; }\n#upl-wpp-hero .wph-trust-item { display: flex !important; align-items: center !important; gap: 7px !important; }\n#upl-wpp-hero .wph-trust-item svg { width: 16px !important; height: 16px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.3 !important; stroke-linecap: round !important; stroke-linejoin: round !important; flex-shrink: 0 !important; }\n#upl-wpp-hero .wph-trust-item span { font-size: 0.82rem !important; color: #64748b !important; font-weight: 500 !important; }\n\/* Visual: PHP code editor mockup *\/\n#upl-wpp-hero .wph-visual { position: relative !important; }\n#upl-wpp-hero .wph-code-wrapper { border-radius: 14px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-hero .wph-editor-bar { background: #161b22 !important; padding: 12px 18px !important; display: flex !important; align-items: center !important; gap: 8px !important; border-bottom: 1px solid rgba(255,255,255,0.06) !important; }\n#upl-wpp-hero .wph-dot { width: 12px !important; height: 12px !important; border-radius: 50% !important; display: inline-block !important; flex-shrink: 0 !important; }\n#upl-wpp-hero .wph-dot-r { background: #ff5f57 !important; }\n#upl-wpp-hero .wph-dot-y { background: #febc2e !important; }\n#upl-wpp-hero .wph-dot-g { background: #28c840 !important; }\n#upl-wpp-hero .wph-filename { color: #8b949e !important; font-size: 13px !important; margin-left: 6px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-hero .wph-editor-logo { width: 16px !important; height: 16px !important; margin-left: auto !important; opacity: 0.9 !important; }\n#upl-wpp-hero .wph-pre { padding: 22px 24px !important; font-size: 13px !important; line-height: 1.8 !important; overflow-x: auto !important; background: #0d1117 !important; }\n#upl-wpp-hero .wph-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-hero .wph-c { color: #8b949e !important; }\n#upl-wpp-hero .wph-k { color: #ff7b72 !important; }\n#upl-wpp-hero .wph-fn { color: #d2a8ff !important; }\n#upl-wpp-hero .wph-s { color: #a5d6ff !important; }\n#upl-wpp-hero .wph-w { color: #e6edf3 !important; }\n#upl-wpp-hero .wph-editor-ok { background: rgba(59,185,139,0.1) !important; border-top: 1px solid rgba(59,185,139,0.25) !important; color: #3BB98B !important; padding: 11px 24px !important; font-size: 12.5px !important; font-family: 'Courier New', monospace !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-hero .wph-editor-ok svg { width: 14px !important; height: 14px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.5 !important; flex-shrink: 0 !important; }\n#upl-wpp-hero .wph-providers { display: flex !important; align-items: center !important; gap: 12px !important; padding: 14px 20px !important; background: #ffffff !important; border-top: 1px solid #e8ecf0 !important; flex-wrap: wrap !important; }\n#upl-wpp-hero .wph-providers span:not(.wph-providers-label) { font-size: 0.72rem !important; color: #94a3b8 !important; }\n#upl-wpp-hero .wph-providers-label { font-size: 0.72rem !important; color: #94a3b8 !important; font-weight: 600 !important; margin-right: 2px !important; }\n#upl-wpp-hero .wph-providers img { width: 18px !important; height: 18px !important; }\n@media (max-width: 900px) {\n  #upl-wpp-hero .wph-container { grid-template-columns: 1fr !important; gap: 40px !important; }\n  #upl-wpp-hero h1 { font-size: 34px !important; }\n  #upl-wpp-hero .wph-pre { font-size: 12px !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-hero { padding: 40px 16px 44px !important; }\n  #upl-wpp-hero h1 { font-size: 28px !important; }\n  #upl-wpp-hero .wph-desc { font-size: 15px !important; }\n  #upl-wpp-hero .wph-actions { width: 100% !important; flex-direction: column !important; align-items: stretch !important; gap: 10px !important; }\n  #upl-wpp-hero .wph-cta-primary, #upl-wpp-hero .wph-cta-secondary { width: 100% !important; justify-content: center !important; }\n  #upl-wpp-hero .wph-pre { padding: 16px !important; font-size: 11.5px !important; }\n}\n@media (max-width: 400px) {\n  #upl-wpp-hero h1 { font-size: 26px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-hero\">\n  <div class=\"wph-container\">\n    <div class=\"wph-content\">\n      <div class=\"wph-badge\"><span class=\"wph-badge-dot\"><\/span><span>WhatsApp API PHP Guide<\/span><\/div>\n      <h1>WhatsApp API with <span>PHP<\/span>: The Complete Integration Guide<\/h1>\n      <div class=\"wph-desc\">Guzzle and cURL calls to connect a WhatsApp account, send and receive messages, manage groups and run the whole thing inside a <strong>Laravel<\/strong> application, without registering a Meta Business app. This is the <strong>WhatsApp API in PHP<\/strong> end to end: connection, webhooks, multi-tenant SaaS and the real cost per message.<\/div>\n      <div class=\"wph-actions\">\n        <a class=\"wph-cta-primary\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n          <span>Start building for free<\/span>\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n        <\/a>\n        <a class=\"wph-cta-secondary\" href=\"#wpp-connect\" data-upl-link=\"#wpp-connect\"><span>Jump to the code<\/span><\/a>\n      <\/div>\n      <div class=\"wph-trust\">\n        <div class=\"wph-trust-item\"><svg viewBox=\"0 0 24 24\"><path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"><\/path><polyline points=\"22 4 12 14.01 9 11.01\"><\/polyline><\/svg><span>No Meta Business verification<\/span><\/div>\n        <div class=\"wph-trust-item\"><svg viewBox=\"0 0 24 24\"><path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"><\/path><polyline points=\"22 4 12 14.01 9 11.01\"><\/polyline><\/svg><span>Guzzle &amp; cURL, no abandoned SDK<\/span><\/div>\n      <\/div>\n    <\/div>\n<div class=\"wph-visual\">\n      <div class=\"wph-code-wrapper\">\n        <div class=\"wph-editor-bar\">\n          <span class=\"wph-dot wph-dot-r\"><\/span><span class=\"wph-dot wph-dot-y\"><\/span><span class=\"wph-dot wph-dot-g\"><\/span>\n          <span class=\"wph-filename\">connect-whatsapp.php<\/span>\n          <img decoding=\"async\" class=\"wph-editor-logo\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2025\/09\/whatsapp-1.svg\" alt=\"WhatsApp API PHP integration\">\n        <\/div>\n        <div class=\"wph-pre\"><code><span class=\"wph-k\">use<\/span> <span class=\"wph-w\">GuzzleHttp\\Client;<\/span>&#10;&#10;<span class=\"wph-w\">$client = <\/span><span class=\"wph-k\">new<\/span> <span class=\"wph-fn\">Client<\/span><span class=\"wph-w\">([<\/span>&#10;<span class=\"wph-w\">  'base_uri' => <\/span><span class=\"wph-s\">'https:\/\/api1.unipile.com:13111'<\/span><span class=\"wph-w\">,<\/span>&#10;<span class=\"wph-w\">  'headers' => [<\/span><span class=\"wph-s\">'X-API-KEY'<\/span><span class=\"wph-w\"> => $apiKey],<\/span>&#10;<span class=\"wph-w\">]);<\/span>&#10;&#10;<span class=\"wph-c\">\/\/ Provider WHATSAPP: no Meta app, no WABA<\/span>&#10;<span class=\"wph-w\">$res = $client-><\/span><span class=\"wph-fn\">post<\/span><span class=\"wph-w\">(<\/span><span class=\"wph-s\">'\/api\/v1\/accounts'<\/span><span class=\"wph-w\">, [<\/span>&#10;<span class=\"wph-w\">  'json' => ['provider' => <\/span><span class=\"wph-s\">'WHATSAPP'<\/span><span class=\"wph-w\">],<\/span>&#10;<span class=\"wph-w\">]);<\/span><\/code><\/div>\n        <div class=\"wph-editor-ok\"><svg viewBox=\"0 0 24 24\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>201 Created, account_id returned<\/span><\/div>\n        <div class=\"wph-providers\">\n          <span class=\"wph-providers-label\">Same pattern for<\/span>\n          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/linkedin-5.svg\" alt=\"LinkedIn\">\n          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg\" alt=\"Gmail\">\n          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/outlook-2.svg\" alt=\"Outlook\">\n          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/imap-1.svg\" alt=\"IMAP\">\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-hero');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (url.charAt(0) === '#') {\n        var dest = document.getElementById(url.substring(1));\n        if (dest) {\n          e.preventDefault();\n          window.scrollTo({ top: dest.getBoundingClientRect().top + window.pageYOffset - 80, behavior: 'smooth' });\n        }\n        return;\n      }\n      e.preventDefault();\n      e.stopPropagation();\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-what\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-what { background: transparent !important; }\n#upl-wpp-what *, #upl-wpp-what *::before, #upl-wpp-what *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-what br { display: none !important; }\n#upl-wpp-what p { display: contents !important; }\n#upl-wpp-what { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-what .wpw-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-what .wpw-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-what .wpw-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-what h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-what .wpw-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 20px !important; }\n#upl-wpp-what .wpw-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-what .wpw-lead code, #upl-wpp-what .wpw-text code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-what .wpw-text { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; margin-bottom: 32px !important; }\n#upl-wpp-what .wpw-text a { color: #2aaa7e !important; text-decoration: underline !important; }\n#upl-wpp-what .wpw-strip { display: grid !important; grid-template-columns: repeat(3, 1fr) !important; gap: 16px !important; }\n#upl-wpp-what .wpw-item { display: flex !important; align-items: flex-start !important; gap: 12px !important; padding: 18px !important; background: #ffffff !important; border: 1px solid #e5e7eb !important; border-radius: 12px !important; }\n#upl-wpp-what .wpw-item-icon { width: 32px !important; height: 32px !important; min-width: 32px !important; background: rgba(59,185,139,0.12) !important; border-radius: 8px !important; display: flex !important; align-items: center !important; justify-content: center !important; }\n#upl-wpp-what .wpw-item-icon svg { width: 16px !important; height: 16px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-what .wpw-item-title { font-size: 0.92rem !important; font-weight: 600 !important; color: #0f2736 !important; margin-bottom: 4px !important; line-height: 1.4 !important; }\n#upl-wpp-what .wpw-item-desc { font-size: 0.82rem !important; color: #64748b !important; line-height: 1.5 !important; }\n@media (max-width: 900px) {\n  #upl-wpp-what h2 { font-size: 28px !important; }\n  #upl-wpp-what .wpw-strip { grid-template-columns: 1fr !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-what { padding: 40px 16px !important; }\n  #upl-wpp-what h2 { font-size: 26px !important; }\n  #upl-wpp-what .wpw-lead, #upl-wpp-what .wpw-text { font-size: 15px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-what\">\n  <div class=\"wpw-container\">\n    <div class=\"wpw-badge\"><span class=\"wpw-badge-dot\"><\/span><span>Definition<\/span><\/div>\n    <h2>What is the WhatsApp API in PHP?<\/h2>\n    <div class=\"wpw-lead\">The <strong>WhatsApp API in PHP<\/strong> is the practice of calling a WhatsApp REST API from a PHP runtime, PHP-FPM, a CLI script or a queue worker, using an HTTP client such as Guzzle or cURL. There is no WhatsApp API built specifically for PHP: Meta and API providers expose plain JSON over HTTPS, and PHP is simply the language making the request, the same way it would call any other web API.<\/div>\n    <div class=\"wpw-text\">In practice, a WhatsApp API PHP integration is a normal HTTP call: a method, a URL, a JSON or multipart body, and an <code>X-API-KEY<\/code> header. Nothing here depends on a PHP-only feature or a PHP-only endpoint. What changes between Cloud API, a Business Solution Provider (BSP), and a linked account is not the language, it is who owns the WhatsApp number and whether Meta Business verification sits between you and your first message. For the full breakdown of that ecosystem, see the <a href=\"https:\/\/www.unipile.com\/whatsapp-api-a-complete-guide-to-integration\/\">WhatsApp API integration guide<\/a>.<\/div>\n<div class=\"wpw-strip\">\n      <div class=\"wpw-item\">\n        <div class=\"wpw-item-icon\"><svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"\/><polyline points=\"8 6 2 12 8 18\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpw-item-title\">Plain JSON over HTTPS<\/div>\n          <div class=\"wpw-item-desc\">Every call is a request\/response cycle Guzzle or cURL already know how to make.<\/div>\n        <\/div>\n      <\/div>\n      <div class=\"wpw-item\">\n        <div class=\"wpw-item-icon\"><svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpw-item-title\">Auth is a static header<\/div>\n          <div class=\"wpw-item-desc\">An <code>X-API-KEY<\/code> value, no OAuth dance, no token refresh loop to write.<\/div>\n        <\/div>\n      <\/div>\n      <div class=\"wpw-item\">\n        <div class=\"wpw-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M20 6L9 17l-5-5\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpw-item-title\">Runtime-agnostic<\/div>\n          <div class=\"wpw-item-desc\">Works the same in PHP-FPM, a Symfony console command, or a Laravel queue job.<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-which\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-which { background: transparent !important; }\n#upl-wpp-which *, #upl-wpp-which *::before, #upl-wpp-which *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-which br { display: none !important; }\n#upl-wpp-which p { display: contents !important; }\n#upl-wpp-which { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-which .wpk-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-which .wpk-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(221,223,76,0.18) !important; color: #8a8c2e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-which .wpk-badge-dot { width: 7px !important; height: 7px !important; background: #DDDF4C !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-which h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-which .wpk-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 34px !important; }\n#upl-wpp-which .wpk-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-which .wpk-table { border: 1px solid #e5e7eb !important; border-radius: 16px !important; overflow: hidden !important; margin-bottom: 24px !important; }\n#upl-wpp-which .wpk-row { display: grid !important; grid-template-columns: 1.1fr 1fr 1fr 1fr !important; }\n#upl-wpp-which .wpk-row:not(:last-child) { border-bottom: 1px solid #e5e7eb !important; }\n#upl-wpp-which .wpk-head { background: #0f2736 !important; }\n#upl-wpp-which .wpk-cell { padding: 16px 18px !important; display: flex !important; align-items: center !important; font-size: 0.86rem !important; color: #1e293b !important; line-height: 1.5 !important; }\n#upl-wpp-which .wpk-head .wpk-cell { color: #ffffff !important; font-weight: 600 !important; font-size: 0.82rem !important; }\n#upl-wpp-which .wpk-head .wpk-cell:first-child { color: rgba(255,255,255,0.65) !important; }\n#upl-wpp-which .wpk-head .wpk-cell.wpk-highlight { background: rgba(59,185,139,0.22) !important; }\n#upl-wpp-which .wpk-cell:first-child { font-weight: 600 !important; color: #0f2736 !important; background: #f8fafc !important; }\n#upl-wpp-which .wpk-cell.wpk-highlight { background: rgba(59,185,139,0.05) !important; }\n#upl-wpp-which .wpk-cell:not(:first-child):not(:last-child) { border-right: 1px solid #f0f1f3 !important; }\n#upl-wpp-which .wpk-no { color: #dc2626 !important; font-weight: 600 !important; }\n#upl-wpp-which .wpk-yes { color: #2aaa7e !important; font-weight: 600 !important; }\n#upl-wpp-which .wpk-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; margin-bottom: 26px !important; }\n#upl-wpp-which .wpk-outro a { color: #2aaa7e !important; text-decoration: underline !important; }\n#upl-wpp-which .wpk-cta { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: #DDDF4C !important; color: #0f2736 !important; padding: 13px 26px !important; border-radius: 8px !important; font-size: 0.92rem !important; font-weight: 600 !important; border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-which .wpk-cta:hover { transform: translateY(-5px) !important; }\n#upl-wpp-which .wpk-cta svg { width: 15px !important; height: 15px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n\/* Mobile: table -> stacked cards *\/\n@media (max-width: 900px) {\n  #upl-wpp-which h2 { font-size: 28px !important; }\n  #upl-wpp-which .wpk-row { grid-template-columns: 1fr !important; }\n  #upl-wpp-which .wpk-head { display: none !important; }\n  #upl-wpp-which .wpk-row:not(.wpk-head) { border: 1px solid #e5e7eb !important; border-radius: 12px !important; margin-bottom: 14px !important; overflow: hidden !important; }\n  #upl-wpp-which .wpk-table { border: none !important; }\n  #upl-wpp-which .wpk-cell { border-right: none !important; border-bottom: 1px solid #f0f1f3 !important; }\n  #upl-wpp-which .wpk-cell:first-child { background: #0f2736 !important; color: #ffffff !important; }\n  #upl-wpp-which .wpk-cell:nth-child(2)::before { content: 'Cloud API: ' !important; font-weight: 700 !important; color: #64748b !important; margin-right: 6px !important; }\n  #upl-wpp-which .wpk-cell:nth-child(3)::before { content: 'BSP: ' !important; font-weight: 700 !important; color: #64748b !important; margin-right: 6px !important; }\n  #upl-wpp-which .wpk-cell:nth-child(4)::before { content: 'Linked account: ' !important; font-weight: 700 !important; color: #64748b !important; margin-right: 6px !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-which { padding: 40px 16px !important; }\n  #upl-wpp-which h2 { font-size: 26px !important; }\n  #upl-wpp-which .wpk-lead, #upl-wpp-which .wpk-outro { font-size: 15px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-which\">\n  <div class=\"wpk-container\">\n    <div class=\"wpk-badge\"><span class=\"wpk-badge-dot\"><\/span><span>Decision<\/span><\/div>\n    <h2>Which WhatsApp API should you use from PHP?<\/h2>\n    <div class=\"wpk-lead\">There are three ways to call WhatsApp from a PHP backend: <strong>Meta's Cloud API<\/strong> directly, a <strong>Business Solution Provider (BSP)<\/strong> reselling access to it, or a <strong>linked account<\/strong> through a unified API like Unipile. All three return JSON your PHP code parses the same way, what changes is setup time, whether Meta Business verification sits in front of your first message, and whether you get an existing conversation history or start from zero.<\/div>\n<div class=\"wpk-table\">\n      <div class=\"wpk-row wpk-head\">\n        <div class=\"wpk-cell\">Criteria<\/div>\n        <div class=\"wpk-cell\">Cloud API (direct)<\/div>\n        <div class=\"wpk-cell\">BSP<\/div>\n        <div class=\"wpk-cell wpk-highlight\">Linked account<\/div>\n      <\/div>\n      <div class=\"wpk-row\">\n        <div class=\"wpk-cell\">Meta Business verification<\/div>\n        <div class=\"wpk-cell\"><span class=\"wpk-no\">Required<\/span><\/div>\n        <div class=\"wpk-cell\"><span class=\"wpk-no\">Required<\/span><\/div>\n        <div class=\"wpk-cell wpk-highlight\"><span class=\"wpk-yes\">Not required<\/span><\/div>\n      <\/div>\n      <div class=\"wpk-row\">\n        <div class=\"wpk-cell\">Time to first message<\/div>\n        <div class=\"wpk-cell\">Days to a few weeks<\/div>\n        <div class=\"wpk-cell\">Faster onboarding, same requirements underneath<\/div>\n        <div class=\"wpk-cell wpk-highlight\">Minutes<\/div>\n      <\/div>\n      <div class=\"wpk-row\">\n        <div class=\"wpk-cell\">Phone number<\/div>\n        <div class=\"wpk-cell\">New number registered to a WABA<\/div>\n        <div class=\"wpk-cell\">New number provisioned by the BSP<\/div>\n        <div class=\"wpk-cell wpk-highlight\">The user's own existing WhatsApp number<\/div>\n      <\/div>\n      <div class=\"wpk-row\">\n        <div class=\"wpk-cell\">Access to existing conversations<\/div>\n        <div class=\"wpk-cell\"><span class=\"wpk-no\">No, starts empty<\/span><\/div>\n        <div class=\"wpk-cell\"><span class=\"wpk-no\">No, starts empty<\/span><\/div>\n        <div class=\"wpk-cell wpk-highlight\"><span class=\"wpk-yes\">Yes, full history<\/span><\/div>\n      <\/div>\n      <div class=\"wpk-row\">\n        <div class=\"wpk-cell\">Best fit<\/div>\n        <div class=\"wpk-cell\">One business number broadcasting to many customers<\/div>\n        <div class=\"wpk-cell\">Same, with a managed onboarding layer<\/div>\n        <div class=\"wpk-cell wpk-highlight\">A product where each user links the WhatsApp account they already have<\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpk-outro\">If your PHP application is a SaaS product where every customer connects their own WhatsApp, a linked account removes the Meta verification step entirely. If you are broadcasting from a single company number, the Cloud API or a BSP is the correct starting point instead.<\/div>\n    <a class=\"wpk-cta\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n      <span>Build with a linked account<\/span>\n      <svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n    <\/a>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-which');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      e.preventDefault();\n      e.stopPropagation();\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-prereq\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-prereq { background: transparent !important; }\n#upl-wpp-prereq *, #upl-wpp-prereq *::before, #upl-wpp-prereq *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-prereq br { display: none !important; }\n#upl-wpp-prereq p { display: contents !important; }\n#upl-wpp-prereq { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-prereq .wpq-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-prereq .wpq-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-prereq .wpq-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-prereq h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-prereq .wpq-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 30px !important; }\n#upl-wpp-prereq .wpq-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-prereq .wpq-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-prereq .wpq-grid { display: grid !important; grid-template-columns: repeat(4, 1fr) !important; gap: 14px !important; margin-bottom: 28px !important; }\n#upl-wpp-prereq .wpq-item { padding: 18px !important; background: #ffffff !important; border: 1px solid #e5e7eb !important; border-radius: 12px !important; }\n#upl-wpp-prereq .wpq-item-icon { width: 32px !important; height: 32px !important; background: rgba(59,185,139,0.12) !important; border-radius: 8px !important; display: flex !important; align-items: center !important; justify-content: center !important; margin-bottom: 12px !important; }\n#upl-wpp-prereq .wpq-item-icon svg { width: 16px !important; height: 16px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-prereq .wpq-item-title { font-size: 0.88rem !important; font-weight: 600 !important; color: #0f2736 !important; margin-bottom: 4px !important; line-height: 1.4 !important; }\n#upl-wpp-prereq .wpq-item-desc { font-size: 0.78rem !important; color: #64748b !important; line-height: 1.5 !important; }\n#upl-wpp-prereq .wpq-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; margin-bottom: 28px !important; }\n#upl-wpp-prereq .wpq-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-prereq .wpq-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-prereq .wpq-dot-r { background: #ff5f57 !important; } #upl-wpp-prereq .wpq-dot-y { background: #febc2e !important; } #upl-wpp-prereq .wpq-dot-g { background: #28c840 !important; }\n#upl-wpp-prereq .wpq-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-prereq .wpq-pre { padding: 18px 20px !important; font-size: 13.5px !important; overflow-x: auto !important; }\n#upl-wpp-prereq .wpq-pre code { font-family: 'Courier New', monospace !important; color: #a5d6ff !important; white-space: pre !important; }\n#upl-wpp-prereq .wpq-note { display: flex !important; gap: 16px !important; padding: 22px !important; background: #fffbea !important; border: 1px solid rgba(221,223,76,0.5) !important; border-radius: 12px !important; }\n#upl-wpp-prereq .wpq-note-icon { width: 36px !important; height: 36px !important; min-width: 36px !important; background: rgba(221,223,76,0.3) !important; border-radius: 8px !important; display: flex !important; align-items: center !important; justify-content: center !important; }\n#upl-wpp-prereq .wpq-note-icon svg { width: 18px !important; height: 18px !important; stroke: #8a8c2e !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-prereq .wpq-note-title { font-size: 0.95rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 6px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-prereq .wpq-note-text { font-size: 0.9rem !important; line-height: 1.7 !important; color: #4a5568 !important; }\n#upl-wpp-prereq .wpq-note-text code { font-family: 'Courier New', monospace !important; background: rgba(15,39,54,0.08) !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #0f2736 !important; }\n#upl-wpp-prereq .wpq-note-text strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-prereq .wpq-note-text a { color: #2aaa7e !important; text-decoration: underline !important; }\n@media (max-width: 900px) {\n  #upl-wpp-prereq h2 { font-size: 28px !important; }\n  #upl-wpp-prereq .wpq-grid { grid-template-columns: repeat(2, 1fr) !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-prereq { padding: 40px 16px !important; }\n  #upl-wpp-prereq h2 { font-size: 26px !important; }\n  #upl-wpp-prereq .wpq-lead { font-size: 15px !important; }\n  #upl-wpp-prereq .wpq-grid { grid-template-columns: 1fr !important; }\n  #upl-wpp-prereq .wpq-note { flex-direction: column !important; }\n  #upl-wpp-prereq .wpq-pre { font-size: 12px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-prereq\">\n  <div class=\"wpq-container\">\n    <div class=\"wpq-badge\"><span class=\"wpq-badge-dot\"><\/span><span>Setup<\/span><\/div>\n    <h2>What do you need before writing any PHP code?<\/h2>\n    <div class=\"wpq-lead\">You need <strong>PHP 8.1 or newer<\/strong>, <strong>Composer<\/strong>, the <strong>Guzzle<\/strong> HTTP client and a Unipile API key. No actively maintained PHP SDK exists for Unipile today, so every example in this guide talks to the <code>\/api\/v1<\/code> REST API directly.<\/div>\n<div class=\"wpq-grid\">\n      <div class=\"wpq-item\">\n        <div class=\"wpq-item-icon\"><svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"\/><polyline points=\"8 6 2 12 8 18\"\/><\/svg><\/div>\n        <div class=\"wpq-item-title\">PHP 8.1+<\/div>\n        <div class=\"wpq-item-desc\">Typed properties and named arguments keep the client code short.<\/div>\n      <\/div>\n      <div class=\"wpq-item\">\n        <div class=\"wpq-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M12 2L2 7l10 5 10-5-10-5z\"\/><path d=\"M2 17l10 5 10-5\"\/><path d=\"M2 12l10 5 10-5\"\/><\/svg><\/div>\n        <div class=\"wpq-item-title\">Composer<\/div>\n        <div class=\"wpq-item-desc\">Standard dependency manager, required to pull in Guzzle.<\/div>\n      <\/div>\n      <div class=\"wpq-item\">\n        <div class=\"wpq-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 17l6-6-6-6\"\/><line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\"\/><\/svg><\/div>\n        <div class=\"wpq-item-title\">Guzzle 7<\/div>\n        <div class=\"wpq-item-desc\">HTTP client for JSON and multipart requests, with a cURL fallback.<\/div>\n      <\/div>\n      <div class=\"wpq-item\">\n        <div class=\"wpq-item-icon\"><svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/svg><\/div>\n        <div class=\"wpq-item-title\">Unipile API key<\/div>\n        <div class=\"wpq-item-desc\">Sent as <code>X-API-KEY<\/code> on every request, generated from your dashboard.<\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpq-code-wrapper\">\n      <div class=\"wpq-editor-bar\">\n        <span class=\"wpq-dot wpq-dot-r\"><\/span><span class=\"wpq-dot wpq-dot-y\"><\/span><span class=\"wpq-dot wpq-dot-g\"><\/span>\n        <span class=\"wpq-filename\">terminal<\/span>\n      <\/div>\n      <div class=\"wpq-pre\"><code>composer require guzzlehttp\/guzzle:^7.0<\/code><\/div>\n    <\/div>\n<div class=\"wpq-note\">\n      <div class=\"wpq-note-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"\/><\/svg><\/div>\n      <div>\n        <div class=\"wpq-note-title\">Is there a PHP SDK? Not one you should install.<\/div>\n        <div class=\"wpq-note-text\">A community package, <code>unipile\/unipile-php-sdk<\/code>, exists on Packagist, but it is listed as <strong>abandoned<\/strong>: no commit since October 17, 2023, 5 stars on GitHub, and it targets an old API base URL. Do not run <code>composer require unipile\/unipile-php-sdk<\/code>. The Node.js SDK (<code>unipile-node-sdk<\/code>) is officially maintained and current, but for PHP, Guzzle straight against the REST API is the reliable path, and it is what every example below uses. See <a href=\"https:\/\/docs.guzzlephp.org\/\" target=\"_blank\" rel=\"noopener\">Guzzle's documentation<\/a> for the client options used here.<\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-connect\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-connect { background: transparent !important; }\n#upl-wpp-connect *, #upl-wpp-connect *::before, #upl-wpp-connect *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-connect br { display: none !important; }\n#upl-wpp-connect p { display: contents !important; }\n#upl-wpp-connect { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-connect .wpn-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-connect .wpn-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-connect .wpn-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-connect h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-connect .wpn-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 36px !important; }\n#upl-wpp-connect .wpn-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-connect .wpn-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-connect .wpn-steps { display: flex !important; flex-direction: column !important; gap: 22px !important; margin-bottom: 28px !important; }\n#upl-wpp-connect .wpn-step { display: grid !important; grid-template-columns: 44px 1fr !important; gap: 18px !important; }\n#upl-wpp-connect .wpn-step-num { width: 44px !important; height: 44px !important; border-radius: 12px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; display: flex !important; align-items: center !important; justify-content: center !important; font-family: 'Poppins', sans-serif !important; font-size: 17px !important; font-weight: 700 !important; }\n#upl-wpp-connect .wpn-step-title { font-size: 1.05rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 6px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-connect .wpn-step-desc { font-size: 0.95rem !important; line-height: 1.7 !important; color: #4a5568 !important; margin-bottom: 14px !important; }\n#upl-wpp-connect .wpn-step-desc code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #0f2736 !important; }\n#upl-wpp-connect .wpn-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-connect .wpn-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-connect .wpn-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-connect .wpn-dot-r { background: #ff5f57 !important; } #upl-wpp-connect .wpn-dot-y { background: #febc2e !important; } #upl-wpp-connect .wpn-dot-g { background: #28c840 !important; }\n#upl-wpp-connect .wpn-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-connect .wpn-pre { padding: 18px 20px !important; font-size: 13px !important; line-height: 1.75 !important; overflow-x: auto !important; }\n#upl-wpp-connect .wpn-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-connect .wpn-c { color: #8b949e !important; }\n#upl-wpp-connect .wpn-k { color: #ff7b72 !important; }\n#upl-wpp-connect .wpn-fn { color: #d2a8ff !important; }\n#upl-wpp-connect .wpn-s { color: #a5d6ff !important; }\n#upl-wpp-connect .wpn-w { color: #e6edf3 !important; }\n#upl-wpp-connect .wpn-outro { display: flex !important; gap: 14px !important; padding: 20px 22px !important; background: #f8fafc !important; border-radius: 12px !important; border-left: 3px solid #3BB98B !important; margin-top: 6px !important; }\n#upl-wpp-connect .wpn-outro svg { width: 20px !important; height: 20px !important; min-width: 20px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; margin-top: 2px !important; }\n#upl-wpp-connect .wpn-outro-text { font-size: 0.92rem !important; line-height: 1.7 !important; color: #4a5568 !important; }\n#upl-wpp-connect .wpn-outro-text strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-connect .wpn-outro-text code { font-family: 'Courier New', monospace !important; background: rgba(15,39,54,0.08) !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #0f2736 !important; }\n#upl-wpp-connect .wpn-cta-wrap { margin-top: 28px !important; }\n#upl-wpp-connect .wpn-cta { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: #DDDF4C !important; color: #0f2736 !important; padding: 14px 28px !important; border-radius: 8px !important; font-size: 0.95rem !important; font-weight: 600 !important; border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-connect .wpn-cta:hover { transform: translateY(-5px) !important; }\n#upl-wpp-connect .wpn-cta svg { width: 16px !important; height: 16px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n@media (max-width: 900px) {\n  #upl-wpp-connect h2 { font-size: 28px !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-connect { padding: 40px 16px !important; }\n  #upl-wpp-connect h2 { font-size: 26px !important; }\n  #upl-wpp-connect .wpn-lead { font-size: 15px !important; }\n  #upl-wpp-connect .wpn-step { grid-template-columns: 36px 1fr !important; gap: 12px !important; }\n  #upl-wpp-connect .wpn-step-num { width: 36px !important; height: 36px !important; font-size: 14px !important; }\n  #upl-wpp-connect .wpn-pre { font-size: 11.5px !important; padding: 14px !important; }\n  #upl-wpp-connect .wpn-outro { flex-direction: column !important; }\n}\n<\/style>\n<div id=\"upl-wpp-connect\">\n  <div class=\"wpn-container\">\n    <div class=\"wpn-badge\"><span class=\"wpn-badge-dot\"><\/span><span>Implementation<\/span><\/div>\n    <h2>How do you connect a WhatsApp account from PHP?<\/h2>\n    <div class=\"wpn-lead\">Connecting a WhatsApp account from PHP takes one <code>POST<\/code> request with the provider set to <strong>WHATSAPP<\/strong>, then one user action: the end user scans the returned QR code from WhatsApp &gt; Linked devices, or types a pairing code into their phone if you requested one instead. No Meta developer app, no WABA, no verification step.<\/div>\n<div class=\"wpn-steps\">\n      <div class=\"wpn-step\">\n        <div class=\"wpn-step-num\">1<\/div>\n        <div>\n          <div class=\"wpn-step-title\">Request a checkpoint, QR code by default<\/div>\n          <div class=\"wpn-step-desc\">Call the accounts endpoint with only <code>provider<\/code> set. Unipile returns an <code>account_id<\/code> plus a checkpoint payload built for the QR flow.<\/div>\n          <div class=\"wpn-code-wrapper\">\n            <div class=\"wpn-editor-bar\"><span class=\"wpn-dot wpn-dot-r\"><\/span><span class=\"wpn-dot wpn-dot-y\"><\/span><span class=\"wpn-dot wpn-dot-g\"><\/span><span class=\"wpn-filename\">connect-qr.php<\/span><\/div>\n            <div class=\"wpn-pre\"><code><span class=\"wpn-w\">$response = $client-><\/span><span class=\"wpn-fn\">post<\/span><span class=\"wpn-w\">(<\/span><span class=\"wpn-s\">'\/api\/v1\/accounts'<\/span><span class=\"wpn-w\">, [<\/span>&#10;<span class=\"wpn-w\">    'json' => ['provider' => <\/span><span class=\"wpn-s\">'WHATSAPP'<\/span><span class=\"wpn-w\">],<\/span>&#10;<span class=\"wpn-w\">]);<\/span>&#10;&#10;<span class=\"wpn-w\">$payload = <\/span><span class=\"wpn-fn\">json_decode<\/span><span class=\"wpn-w\">($response-><\/span><span class=\"wpn-fn\">getBody<\/span><span class=\"wpn-w\">()-><\/span><span class=\"wpn-fn\">getContents<\/span><span class=\"wpn-w\">(), <\/span><span class=\"wpn-k\">true<\/span><span class=\"wpn-w\">);<\/span>&#10;<span class=\"wpn-w\">$accountId = $payload[<\/span><span class=\"wpn-s\">'account_id'<\/span><span class=\"wpn-w\">];<\/span>&#10;&#10;<span class=\"wpn-c\">\/\/ $payload also carries the checkpoint to render to the<\/span>&#10;<span class=\"wpn-c\">\/\/ end user: the QR code to scan from WhatsApp > Linked<\/span>&#10;<span class=\"wpn-c\">\/\/ devices. var_dump($payload) once against your own key<\/span>&#10;<span class=\"wpn-c\">\/\/ to see the exact shape before wiring up the frontend.<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpn-step\">\n        <div class=\"wpn-step-num\">2<\/div>\n        <div>\n          <div class=\"wpn-step-title\">Or request a pairing code instead<\/div>\n          <div class=\"wpn-step-desc\">Pass <code>pairing_phone_number<\/code> in E.164 digits, no plus sign, when scanning a QR code is not practical, for example a support agent onboarding a client by phone.<\/div>\n          <div class=\"wpn-code-wrapper\">\n            <div class=\"wpn-editor-bar\"><span class=\"wpn-dot wpn-dot-r\"><\/span><span class=\"wpn-dot wpn-dot-y\"><\/span><span class=\"wpn-dot wpn-dot-g\"><\/span><span class=\"wpn-filename\">connect-pairing.php<\/span><\/div>\n            <div class=\"wpn-pre\"><code><span class=\"wpn-w\">$response = $client-><\/span><span class=\"wpn-fn\">post<\/span><span class=\"wpn-w\">(<\/span><span class=\"wpn-s\">'\/api\/v1\/accounts'<\/span><span class=\"wpn-w\">, [<\/span>&#10;<span class=\"wpn-w\">    'json' => [<\/span>&#10;<span class=\"wpn-w\">        'provider' => <\/span><span class=\"wpn-s\">'WHATSAPP'<\/span><span class=\"wpn-w\">,<\/span>&#10;<span class=\"wpn-w\">        'pairing_phone_number' => <\/span><span class=\"wpn-s\">'33612345678'<\/span><span class=\"wpn-w\">,<\/span>&#10;<span class=\"wpn-w\">    ],<\/span>&#10;<span class=\"wpn-w\">]);<\/span>&#10;&#10;<span class=\"wpn-w\">$payload = <\/span><span class=\"wpn-fn\">json_decode<\/span><span class=\"wpn-w\">($response-><\/span><span class=\"wpn-fn\">getBody<\/span><span class=\"wpn-w\">()-><\/span><span class=\"wpn-fn\">getContents<\/span><span class=\"wpn-w\">(), <\/span><span class=\"wpn-k\">true<\/span><span class=\"wpn-w\">);<\/span>&#10;<span class=\"wpn-w\">$accountId = $payload[<\/span><span class=\"wpn-s\">'account_id'<\/span><span class=\"wpn-w\">];<\/span>&#10;&#10;<span class=\"wpn-c\">\/\/ The checkpoint here is the code your UI shows the user<\/span>&#10;<span class=\"wpn-c\">\/\/ to type into WhatsApp > Linked devices > Link with<\/span>&#10;<span class=\"wpn-c\">\/\/ phone number instead.<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpn-step\">\n        <div class=\"wpn-step-num\">3<\/div>\n        <div>\n          <div class=\"wpn-step-title\">Poll until the account is fully linked<\/div>\n          <div class=\"wpn-step-desc\">The account stays in a <code>CONNECTING<\/code> state until the QR code is scanned or the pairing code is entered. Check <code>sources[0].status<\/code> on the account.<\/div>\n          <div class=\"wpn-code-wrapper\">\n            <div class=\"wpn-editor-bar\"><span class=\"wpn-dot wpn-dot-r\"><\/span><span class=\"wpn-dot wpn-dot-y\"><\/span><span class=\"wpn-dot wpn-dot-g\"><\/span><span class=\"wpn-filename\">poll-status.php<\/span><\/div>\n            <div class=\"wpn-pre\"><code><span class=\"wpn-w\">$response = $client-><\/span><span class=\"wpn-fn\">get<\/span><span class=\"wpn-w\">(<\/span><span class=\"wpn-s\">\"\/api\/v1\/accounts\/{$accountId}\"<\/span><span class=\"wpn-w\">);<\/span>&#10;<span class=\"wpn-w\">$account = <\/span><span class=\"wpn-fn\">json_decode<\/span><span class=\"wpn-w\">($response-><\/span><span class=\"wpn-fn\">getBody<\/span><span class=\"wpn-w\">()-><\/span><span class=\"wpn-fn\">getContents<\/span><span class=\"wpn-w\">(), <\/span><span class=\"wpn-k\">true<\/span><span class=\"wpn-w\">);<\/span>&#10;<span class=\"wpn-w\">$status = $account[<\/span><span class=\"wpn-s\">'sources'<\/span><span class=\"wpn-w\">][0][<\/span><span class=\"wpn-s\">'status'<\/span><span class=\"wpn-w\">] ?? <\/span><span class=\"wpn-k\">null<\/span><span class=\"wpn-w\">;<\/span>&#10;&#10;<span class=\"wpn-k\">if<\/span><span class=\"wpn-w\"> ($status === <\/span><span class=\"wpn-s\">'OK'<\/span><span class=\"wpn-w\">) {<\/span>&#10;<span class=\"wpn-w\">    <\/span><span class=\"wpn-c\">\/\/ safe to send, receive and list chats on $accountId<\/span>&#10;<span class=\"wpn-w\">}<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpn-outro\">\n      <svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"\/><\/svg>\n      <div class=\"wpn-outro-text\">Polling in a loop works but wastes requests. If your PHP application already has a webhook endpoint, register one with <code>source: \"account_status\"<\/code> instead and react the moment the status flips to <strong>OK<\/strong>. The webhook setup itself is covered further down for incoming messages, the same endpoint accepts account status events.<\/div>\n    <\/div>\n<div class=\"wpn-cta-wrap\">\n      <a class=\"wpn-cta\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n        <span>Build your connection flow<\/span>\n        <svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n      <\/a>\n    <\/div>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-connect');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      e.preventDefault();\n      e.stopPropagation();\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-send\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-send { background: transparent !important; }\n#upl-wpp-send *, #upl-wpp-send *::before, #upl-wpp-send *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-send br { display: none !important; }\n#upl-wpp-send p { display: contents !important; }\n#upl-wpp-send { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-send .wps-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-send .wps-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-send .wps-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-send h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-send .wps-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 26px !important; }\n#upl-wpp-send .wps-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-send .wps-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-send .wps-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; margin-bottom: 24px !important; }\n#upl-wpp-send .wps-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-send .wps-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-send .wps-dot-r { background: #ff5f57 !important; } #upl-wpp-send .wps-dot-y { background: #febc2e !important; } #upl-wpp-send .wps-dot-g { background: #28c840 !important; }\n#upl-wpp-send .wps-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-send .wps-pre { padding: 18px 20px !important; font-size: 13px !important; line-height: 1.75 !important; overflow-x: auto !important; }\n#upl-wpp-send .wps-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-send .wps-c { color: #8b949e !important; }\n#upl-wpp-send .wps-k { color: #ff7b72 !important; }\n#upl-wpp-send .wps-fn { color: #d2a8ff !important; }\n#upl-wpp-send .wps-s { color: #a5d6ff !important; }\n#upl-wpp-send .wps-w { color: #e6edf3 !important; }\n#upl-wpp-send .wps-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; }\n#upl-wpp-send .wps-outro a { color: #2aaa7e !important; text-decoration: underline !important; }\n@media (max-width: 900px) { #upl-wpp-send h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-send { padding: 40px 16px !important; }\n  #upl-wpp-send h2 { font-size: 26px !important; }\n  #upl-wpp-send .wps-lead, #upl-wpp-send .wps-outro { font-size: 15px !important; }\n  #upl-wpp-send .wps-pre { font-size: 11.5px !important; padding: 14px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-send\">\n  <div class=\"wps-container\">\n    <div class=\"wps-badge\"><span class=\"wps-badge-dot\"><\/span><span>Core flow<\/span><\/div>\n    <h2>How do you send a WhatsApp message with PHP and Guzzle?<\/h2>\n    <div class=\"wps-lead\">Sending a message from PHP is one <code>POST<\/code> to the chat's messages endpoint with a <code>text<\/code> field in a multipart body. The call returns a <code>message_id<\/code> the instant WhatsApp accepts it.<\/div>\n<div class=\"wps-code-wrapper\">\n      <div class=\"wps-editor-bar\"><span class=\"wps-dot wps-dot-r\"><\/span><span class=\"wps-dot wps-dot-y\"><\/span><span class=\"wps-dot wps-dot-g\"><\/span><span class=\"wps-filename\">send-message.php<\/span><\/div>\n      <div class=\"wps-pre\"><code><span class=\"wps-w\">$response = $client-><\/span><span class=\"wps-fn\">post<\/span><span class=\"wps-w\">(<\/span><span class=\"wps-s\">\"\/api\/v1\/chats\/{$chatId}\/messages\"<\/span><span class=\"wps-w\">, [<\/span>&#10;<span class=\"wps-w\">    'multipart' => [<\/span>&#10;<span class=\"wps-w\">        [<\/span><span class=\"wps-s\">'name'<\/span><span class=\"wps-w\"> => <\/span><span class=\"wps-s\">'text'<\/span><span class=\"wps-w\">, <\/span><span class=\"wps-s\">'contents'<\/span><span class=\"wps-w\"> => <\/span><span class=\"wps-s\">'Hi! Your order has shipped.'<\/span><span class=\"wps-w\">],<\/span>&#10;<span class=\"wps-w\">    ],<\/span>&#10;<span class=\"wps-w\">]);<\/span>&#10;&#10;<span class=\"wps-w\">$result = <\/span><span class=\"wps-fn\">json_decode<\/span><span class=\"wps-w\">($response-><\/span><span class=\"wps-fn\">getBody<\/span><span class=\"wps-w\">()-><\/span><span class=\"wps-fn\">getContents<\/span><span class=\"wps-w\">(), <\/span><span class=\"wps-k\">true<\/span><span class=\"wps-w\">);<\/span>&#10;<span class=\"wps-w\">$messageId = $result[<\/span><span class=\"wps-s\">'message_id'<\/span><span class=\"wps-w\">];<\/span><\/code><\/div>\n    <\/div>\n<div class=\"wps-outro\">The same <code>multipart<\/code> array also carries <code>attachments<\/code>, a <code>voice_message<\/code> file, or a <code>quote_id<\/code> to reply to a specific message, Guzzle attaches them as additional multipart fields next to <code>text<\/code>. For the full breakdown of every <a href=\"https:\/\/www.unipile.com\/whatsapp-api-to-send-messages\/\">message type the WhatsApp API supports<\/a>, including templates and the 24-hour service window, see our dedicated guide.<\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-start\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-start { background: transparent !important; }\n#upl-wpp-start *, #upl-wpp-start *::before, #upl-wpp-start *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-start br { display: none !important; }\n#upl-wpp-start p { display: contents !important; }\n#upl-wpp-start { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-start .wpt-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-start .wpt-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-start .wpt-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-start h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-start .wpt-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 26px !important; }\n#upl-wpp-start .wpt-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-start .wpt-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-start .wpt-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; margin-bottom: 24px !important; }\n#upl-wpp-start .wpt-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-start .wpt-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-start .wpt-dot-r { background: #ff5f57 !important; } #upl-wpp-start .wpt-dot-y { background: #febc2e !important; } #upl-wpp-start .wpt-dot-g { background: #28c840 !important; }\n#upl-wpp-start .wpt-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-start .wpt-pre { padding: 18px 20px !important; font-size: 13px !important; line-height: 1.75 !important; overflow-x: auto !important; }\n#upl-wpp-start .wpt-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-start .wpt-c { color: #8b949e !important; }\n#upl-wpp-start .wpt-k { color: #ff7b72 !important; }\n#upl-wpp-start .wpt-fn { color: #d2a8ff !important; }\n#upl-wpp-start .wpt-s { color: #a5d6ff !important; }\n#upl-wpp-start .wpt-w { color: #e6edf3 !important; }\n#upl-wpp-start .wpt-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; }\n@media (max-width: 900px) { #upl-wpp-start h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-start { padding: 40px 16px !important; }\n  #upl-wpp-start h2 { font-size: 26px !important; }\n  #upl-wpp-start .wpt-lead, #upl-wpp-start .wpt-outro { font-size: 15px !important; }\n  #upl-wpp-start .wpt-pre { font-size: 11.5px !important; padding: 14px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-start\">\n  <div class=\"wpt-container\">\n    <div class=\"wpt-badge\"><span class=\"wpt-badge-dot\"><\/span><span>Core flow<\/span><\/div>\n    <h2>How do you start a new conversation from PHP?<\/h2>\n    <div class=\"wpt-lead\">Starting a conversation that does not exist yet means calling the chats endpoint with an <code>account_id<\/code> and an <code>attendees_ids<\/code> array instead of an existing <code>chat_id<\/code>. Unipile creates the chat and, if you include a <code>text<\/code> field, sends the first message in the same call.<\/div>\n<div class=\"wpt-code-wrapper\">\n      <div class=\"wpt-editor-bar\"><span class=\"wpt-dot wpt-dot-r\"><\/span><span class=\"wpt-dot wpt-dot-y\"><\/span><span class=\"wpt-dot wpt-dot-g\"><\/span><span class=\"wpt-filename\">start-conversation.php<\/span><\/div>\n      <div class=\"wpt-pre\"><code><span class=\"wpt-w\">$response = $client-><\/span><span class=\"wpt-fn\">post<\/span><span class=\"wpt-w\">(<\/span><span class=\"wpt-s\">'\/api\/v1\/chats'<\/span><span class=\"wpt-w\">, [<\/span>&#10;<span class=\"wpt-w\">    'multipart' => [<\/span>&#10;<span class=\"wpt-w\">        [<\/span><span class=\"wpt-s\">'name'<\/span><span class=\"wpt-w\"> => <\/span><span class=\"wpt-s\">'account_id'<\/span><span class=\"wpt-w\">, <\/span><span class=\"wpt-s\">'contents'<\/span><span class=\"wpt-w\"> => $accountId],<\/span>&#10;<span class=\"wpt-w\">        [<\/span><span class=\"wpt-s\">'name'<\/span><span class=\"wpt-w\"> => <\/span><span class=\"wpt-s\">'attendees_ids[]'<\/span><span class=\"wpt-w\">, <\/span><span class=\"wpt-s\">'contents'<\/span><span class=\"wpt-w\"> => <\/span><span class=\"wpt-s\">'33612345678@s.whatsapp.net'<\/span><span class=\"wpt-w\">],<\/span>&#10;<span class=\"wpt-w\">        [<\/span><span class=\"wpt-s\">'name'<\/span><span class=\"wpt-w\"> => <\/span><span class=\"wpt-s\">'text'<\/span><span class=\"wpt-w\">, <\/span><span class=\"wpt-s\">'contents'<\/span><span class=\"wpt-w\"> => <\/span><span class=\"wpt-s\">'Hi, this is Acme support.'<\/span><span class=\"wpt-w\">],<\/span>&#10;<span class=\"wpt-w\">    ],<\/span>&#10;<span class=\"wpt-w\">]);<\/span>&#10;&#10;<span class=\"wpt-w\">$result = <\/span><span class=\"wpt-fn\">json_decode<\/span><span class=\"wpt-w\">($response-><\/span><span class=\"wpt-fn\">getBody<\/span><span class=\"wpt-w\">()-><\/span><span class=\"wpt-fn\">getContents<\/span><span class=\"wpt-w\">(), <\/span><span class=\"wpt-k\">true<\/span><span class=\"wpt-w\">);<\/span>&#10;<span class=\"wpt-w\">$chatId = $result[<\/span><span class=\"wpt-s\">'chat_id'<\/span><span class=\"wpt-w\">];<\/span><\/code><\/div>\n    <\/div>\n<div class=\"wpt-outro\">The recipient is identified by <code>{phone_number}@s.whatsapp.net<\/code>, international digits, no leading plus sign, no spaces. Store the returned <code>chat_id<\/code> next to that user record: every message after the first one goes through the messages endpoint from the previous section, not through this one.<\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-retrieve\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-retrieve { background: transparent !important; }\n#upl-wpp-retrieve *, #upl-wpp-retrieve *::before, #upl-wpp-retrieve *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-retrieve br { display: none !important; }\n#upl-wpp-retrieve p { display: contents !important; }\n#upl-wpp-retrieve { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-retrieve .wpv-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-retrieve .wpv-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-retrieve .wpv-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-retrieve h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-retrieve .wpv-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 30px !important; }\n#upl-wpp-retrieve .wpv-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-retrieve .wpv-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-retrieve .wpv-cols { display: grid !important; grid-template-columns: 1fr 1fr !important; gap: 20px !important; margin-bottom: 24px !important; }\n#upl-wpp-retrieve .wpv-col-title { font-size: 0.9rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 10px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-retrieve .wpv-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-retrieve .wpv-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-retrieve .wpv-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-retrieve .wpv-dot-r { background: #ff5f57 !important; } #upl-wpp-retrieve .wpv-dot-y { background: #febc2e !important; } #upl-wpp-retrieve .wpv-dot-g { background: #28c840 !important; }\n#upl-wpp-retrieve .wpv-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-retrieve .wpv-pre { padding: 16px 18px !important; font-size: 12.3px !important; line-height: 1.72 !important; overflow-x: auto !important; }\n#upl-wpp-retrieve .wpv-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-retrieve .wpv-c { color: #8b949e !important; }\n#upl-wpp-retrieve .wpv-k { color: #ff7b72 !important; }\n#upl-wpp-retrieve .wpv-fn { color: #d2a8ff !important; }\n#upl-wpp-retrieve .wpv-s { color: #a5d6ff !important; }\n#upl-wpp-retrieve .wpv-w { color: #e6edf3 !important; }\n#upl-wpp-retrieve .wpv-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; }\n#upl-wpp-retrieve .wpv-outro code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n@media (max-width: 900px) {\n  #upl-wpp-retrieve h2 { font-size: 28px !important; }\n  #upl-wpp-retrieve .wpv-cols { grid-template-columns: 1fr !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-retrieve { padding: 40px 16px !important; }\n  #upl-wpp-retrieve h2 { font-size: 26px !important; }\n  #upl-wpp-retrieve .wpv-lead, #upl-wpp-retrieve .wpv-outro { font-size: 15px !important; }\n  #upl-wpp-retrieve .wpv-pre { font-size: 11px !important; padding: 12px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-retrieve\">\n  <div class=\"wpv-container\">\n    <div class=\"wpv-badge\"><span class=\"wpv-badge-dot\"><\/span><span>Core flow<\/span><\/div>\n    <h2>How do you retrieve chats and messages in PHP?<\/h2>\n    <div class=\"wpv-lead\">Most WhatsApp API tutorials stop at sending. A PHP backend usually also needs to list a user's existing conversations, page through their history, and see who is in a chat. Three endpoints cover it: <code>GET \/api\/v1\/chats<\/code>, <code>GET \/api\/v1\/chats\/{chat_id}\/messages<\/code>, and <code>GET \/api\/v1\/chats\/{chat_id}\/attendees<\/code>, all paginated with a cursor.<\/div>\n<div class=\"wpv-cols\">\n      <div>\n        <div class=\"wpv-col-title\">List every WhatsApp chat on an account<\/div>\n        <div class=\"wpv-code-wrapper\">\n          <div class=\"wpv-editor-bar\"><span class=\"wpv-dot wpv-dot-r\"><\/span><span class=\"wpv-dot wpv-dot-y\"><\/span><span class=\"wpv-dot wpv-dot-g\"><\/span><span class=\"wpv-filename\">list-chats.php<\/span><\/div>\n          <div class=\"wpv-pre\"><code><span class=\"wpv-w\">$response = $client-><\/span><span class=\"wpv-fn\">get<\/span><span class=\"wpv-w\">(<\/span><span class=\"wpv-s\">'\/api\/v1\/chats'<\/span><span class=\"wpv-w\">, [<\/span>&#10;<span class=\"wpv-w\">    'query' => [<\/span>&#10;<span class=\"wpv-w\">        'account_id' => $accountId,<\/span>&#10;<span class=\"wpv-w\">        'account_type' => <\/span><span class=\"wpv-s\">'WHATSAPP'<\/span><span class=\"wpv-w\">,<\/span>&#10;<span class=\"wpv-w\">        'limit' => 50,<\/span>&#10;<span class=\"wpv-w\">    ],<\/span>&#10;<span class=\"wpv-w\">]);<\/span>&#10;&#10;<span class=\"wpv-w\">$data = <\/span><span class=\"wpv-fn\">json_decode<\/span><span class=\"wpv-w\">($response-><\/span><span class=\"wpv-fn\">getBody<\/span><span class=\"wpv-w\">()-><\/span><span class=\"wpv-fn\">getContents<\/span><span class=\"wpv-w\">(), <\/span><span class=\"wpv-k\">true<\/span><span class=\"wpv-w\">);<\/span>&#10;<span class=\"wpv-w\">$chats = $data[<\/span><span class=\"wpv-s\">'items'<\/span><span class=\"wpv-w\">];<\/span>&#10;<span class=\"wpv-w\">$nextCursor = $data[<\/span><span class=\"wpv-s\">'cursor'<\/span><span class=\"wpv-w\">];<\/span><\/code><\/div>\n        <\/div>\n      <\/div>\n      <div>\n        <div class=\"wpv-col-title\">Page through one chat's history<\/div>\n        <div class=\"wpv-code-wrapper\">\n          <div class=\"wpv-editor-bar\"><span class=\"wpv-dot wpv-dot-r\"><\/span><span class=\"wpv-dot wpv-dot-y\"><\/span><span class=\"wpv-dot wpv-dot-g\"><\/span><span class=\"wpv-filename\">list-messages.php<\/span><\/div>\n          <div class=\"wpv-pre\"><code><span class=\"wpv-w\">$cursor = <\/span><span class=\"wpv-k\">null<\/span><span class=\"wpv-w\">;<\/span>&#10;<span class=\"wpv-w\">$all = [];<\/span>&#10;&#10;<span class=\"wpv-k\">do<\/span><span class=\"wpv-w\"> {<\/span>&#10;<span class=\"wpv-w\">    $res = $client-><\/span><span class=\"wpv-fn\">get<\/span><span class=\"wpv-w\">(<\/span><span class=\"wpv-s\">\"\/api\/v1\/chats\/{$chatId}\/messages\"<\/span><span class=\"wpv-w\">, [<\/span>&#10;<span class=\"wpv-w\">        'query' => <\/span><span class=\"wpv-fn\">array_filter<\/span><span class=\"wpv-w\">([<\/span><span class=\"wpv-s\">'cursor'<\/span><span class=\"wpv-w\"> => $cursor, <\/span><span class=\"wpv-s\">'limit'<\/span><span class=\"wpv-w\"> => 100]),<\/span>&#10;<span class=\"wpv-w\">    ]);<\/span>&#10;<span class=\"wpv-w\">    $page = <\/span><span class=\"wpv-fn\">json_decode<\/span><span class=\"wpv-w\">($res-><\/span><span class=\"wpv-fn\">getBody<\/span><span class=\"wpv-w\">()-><\/span><span class=\"wpv-fn\">getContents<\/span><span class=\"wpv-w\">(), <\/span><span class=\"wpv-k\">true<\/span><span class=\"wpv-w\">);<\/span>&#10;<span class=\"wpv-w\">    $all = <\/span><span class=\"wpv-fn\">array_merge<\/span><span class=\"wpv-w\">($all, $page[<\/span><span class=\"wpv-s\">'items'<\/span><span class=\"wpv-w\">]);<\/span>&#10;<span class=\"wpv-w\">    $cursor = $page[<\/span><span class=\"wpv-s\">'cursor'<\/span><span class=\"wpv-w\">];<\/span>&#10;<span class=\"wpv-w\">} <\/span><span class=\"wpv-k\">while<\/span><span class=\"wpv-w\"> ($cursor !== <\/span><span class=\"wpv-k\">null<\/span><span class=\"wpv-w\">);<\/span><\/code><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpv-outro\">Every list endpoint follows the same cursor contract: pass the previous response's <code>cursor<\/code> back in, stop when it comes back <code>null<\/code>. To see who is actually in a conversation, call <code>GET \/api\/v1\/chats\/{chat_id}\/attendees<\/code>: it returns each participant's <code>id<\/code>, <code>provider_id<\/code> and display name, which is what you need before you can call <code>addParticipant<\/code> or <code>removeParticipant<\/code> on a group later in this guide.<\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-webhook\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-webhook { background: transparent !important; }\n#upl-wpp-webhook *, #upl-wpp-webhook *::before, #upl-wpp-webhook *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-webhook br { display: none !important; }\n#upl-wpp-webhook p { display: contents !important; }\n#upl-wpp-webhook { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-webhook .wpb-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-webhook .wpb-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(221,223,76,0.18) !important; color: #8a8c2e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-webhook .wpb-badge-dot { width: 7px !important; height: 7px !important; background: #DDDF4C !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-webhook h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-webhook .wpb-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 30px !important; }\n#upl-wpp-webhook .wpb-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-webhook .wpb-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-webhook .wpb-step-title { font-size: 0.9rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 10px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-webhook .wpb-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; margin-bottom: 22px !important; }\n#upl-wpp-webhook .wpb-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-webhook .wpb-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-webhook .wpb-dot-r { background: #ff5f57 !important; } #upl-wpp-webhook .wpb-dot-y { background: #febc2e !important; } #upl-wpp-webhook .wpb-dot-g { background: #28c840 !important; }\n#upl-wpp-webhook .wpb-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-webhook .wpb-pre { padding: 18px 20px !important; font-size: 12.6px !important; line-height: 1.72 !important; overflow-x: auto !important; }\n#upl-wpp-webhook .wpb-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-webhook .wpb-c { color: #8b949e !important; }\n#upl-wpp-webhook .wpb-k { color: #ff7b72 !important; }\n#upl-wpp-webhook .wpb-fn { color: #d2a8ff !important; }\n#upl-wpp-webhook .wpb-s { color: #a5d6ff !important; }\n#upl-wpp-webhook .wpb-w { color: #e6edf3 !important; }\n#upl-wpp-webhook .wpb-note { display: flex !important; gap: 16px !important; padding: 22px !important; background: #f8fafc !important; border-radius: 12px !important; border-left: 3px solid #3BB98B !important; margin-bottom: 8px !important; }\n#upl-wpp-webhook .wpb-note svg { width: 20px !important; height: 20px !important; min-width: 20px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; margin-top: 2px !important; }\n#upl-wpp-webhook .wpb-note-text { font-size: 0.9rem !important; line-height: 1.7 !important; color: #4a5568 !important; }\n#upl-wpp-webhook .wpb-note-text strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-webhook .wpb-note-text code { font-family: 'Courier New', monospace !important; background: rgba(15,39,54,0.08) !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #0f2736 !important; }\n@media (max-width: 900px) { #upl-wpp-webhook h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-webhook { padding: 40px 16px !important; }\n  #upl-wpp-webhook h2 { font-size: 26px !important; }\n  #upl-wpp-webhook .wpb-lead { font-size: 15px !important; }\n  #upl-wpp-webhook .wpb-pre { font-size: 11px !important; padding: 14px !important; }\n  #upl-wpp-webhook .wpb-note { flex-direction: column !important; }\n}\n<\/style>\n<div id=\"upl-wpp-webhook\">\n  <div class=\"wpb-container\">\n    <div class=\"wpb-badge\"><span class=\"wpb-badge-dot\"><\/span><span>Production<\/span><\/div>\n    <h2>How do you receive WhatsApp messages with a PHP webhook?<\/h2>\n    <div class=\"wpb-lead\">A WhatsApp webhook in PHP is a public HTTPS endpoint that Unipile calls with a JSON payload on events like <code>message_received<\/code>. Your script reads the raw body, confirms the call is genuine, replies fast, and hands the actual work to a queue. Polling <code>GET \/api\/v1\/chats<\/code> for new messages works for a demo, not for a product with more than a handful of users.<\/div>\n<div class=\"wpb-step-title\">1. Register the webhook, with a shared secret in a custom header<\/div>\n    <div class=\"wpb-code-wrapper\">\n      <div class=\"wpb-editor-bar\"><span class=\"wpb-dot wpb-dot-r\"><\/span><span class=\"wpb-dot wpb-dot-y\"><\/span><span class=\"wpb-dot wpb-dot-g\"><\/span><span class=\"wpb-filename\">register-webhook.php<\/span><\/div>\n      <div class=\"wpb-pre\"><code><span class=\"wpb-w\">$client-><\/span><span class=\"wpb-fn\">post<\/span><span class=\"wpb-w\">(<\/span><span class=\"wpb-s\">'\/api\/v1\/webhooks'<\/span><span class=\"wpb-w\">, [<\/span>&#10;<span class=\"wpb-w\">    'json' => [<\/span>&#10;<span class=\"wpb-w\">        'source' => <\/span><span class=\"wpb-s\">'messaging'<\/span><span class=\"wpb-w\">,<\/span>&#10;<span class=\"wpb-w\">        'request_url' => <\/span><span class=\"wpb-s\">'https:\/\/example.com\/webhooks\/whatsapp'<\/span><span class=\"wpb-w\">,<\/span>&#10;<span class=\"wpb-w\">        'events' => [<\/span><span class=\"wpb-s\">'message_received'<\/span><span class=\"wpb-w\">],<\/span>&#10;<span class=\"wpb-w\">        'headers' => [<\/span>&#10;<span class=\"wpb-w\">            [<\/span><span class=\"wpb-s\">'key'<\/span><span class=\"wpb-w\"> => <\/span><span class=\"wpb-s\">'X-Webhook-Secret'<\/span><span class=\"wpb-w\">, <\/span><span class=\"wpb-s\">'value'<\/span><span class=\"wpb-w\"> => $webhookSecret],<\/span>&#10;<span class=\"wpb-w\">        ],<\/span>&#10;<span class=\"wpb-w\">    ],<\/span>&#10;<span class=\"wpb-w\">]);<\/span><\/code><\/div>\n    <\/div>\n<div class=\"wpb-step-title\">2. Verify, respond, then process<\/div>\n    <div class=\"wpb-code-wrapper\">\n      <div class=\"wpb-editor-bar\"><span class=\"wpb-dot wpb-dot-r\"><\/span><span class=\"wpb-dot wpb-dot-y\"><\/span><span class=\"wpb-dot wpb-dot-g\"><\/span><span class=\"wpb-filename\">public\/webhooks\/whatsapp.php<\/span><\/div>\n      <div class=\"wpb-pre\"><code><span class=\"wpb-w\">$rawBody = <\/span><span class=\"wpb-fn\">file_get_contents<\/span><span class=\"wpb-w\">(<\/span><span class=\"wpb-s\">'php:\/\/input'<\/span><span class=\"wpb-w\">);<\/span>&#10;<span class=\"wpb-w\">$provided = $_SERVER[<\/span><span class=\"wpb-s\">'HTTP_X_WEBHOOK_SECRET'<\/span><span class=\"wpb-w\">] ?? <\/span><span class=\"wpb-s\">''<\/span><span class=\"wpb-w\">;<\/span>&#10;&#10;<span class=\"wpb-k\">if<\/span><span class=\"wpb-w\"> (!<\/span><span class=\"wpb-fn\">hash_equals<\/span><span class=\"wpb-w\">($expectedSecret, $provided)) {<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-fn\">http_response_code<\/span><span class=\"wpb-w\">(401);<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-k\">exit<\/span><span class=\"wpb-w\">;<\/span>&#10;<span class=\"wpb-w\">}<\/span>&#10;&#10;<span class=\"wpb-fn\">http_response_code<\/span><span class=\"wpb-w\">(200);<\/span>&#10;<span class=\"wpb-k\">if<\/span><span class=\"wpb-w\"> (<\/span><span class=\"wpb-fn\">function_exists<\/span><span class=\"wpb-w\">(<\/span><span class=\"wpb-s\">'fastcgi_finish_request'<\/span><span class=\"wpb-w\">)) {<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-fn\">fastcgi_finish_request<\/span><span class=\"wpb-w\">();<\/span>&#10;<span class=\"wpb-w\">}<\/span>&#10;&#10;<span class=\"wpb-w\">$payload = <\/span><span class=\"wpb-fn\">json_decode<\/span><span class=\"wpb-w\">($rawBody, <\/span><span class=\"wpb-k\">true<\/span><span class=\"wpb-w\">);<\/span>&#10;&#10;<span class=\"wpb-k\">if<\/span><span class=\"wpb-w\"> (($payload[<\/span><span class=\"wpb-s\">'event'<\/span><span class=\"wpb-w\">] ?? <\/span><span class=\"wpb-k\">null<\/span><span class=\"wpb-w\">) === <\/span><span class=\"wpb-s\">'message_received'<\/span><span class=\"wpb-w\">) {<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-c\">\/\/ push $payload to a queue table or Redis list,<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-c\">\/\/ never process a webhook inline<\/span>&#10;<span class=\"wpb-w\">    <\/span><span class=\"wpb-fn\">enqueue_whatsapp_message<\/span><span class=\"wpb-w\">($payload);<\/span>&#10;<span class=\"wpb-w\">}<\/span><\/code><\/div>\n    <\/div>\n<div class=\"wpb-note\">\n      <svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"\/><\/svg>\n      <div class=\"wpb-note-text\">Unipile does not sign the webhook body with an HMAC secret you recompute, the create-webhook endpoint exposes a <code>headers<\/code> array instead. Attach your own secret as a custom header when you register the webhook, then check it with <code>hash_equals()<\/code>, a timing-safe string comparison, before trusting the payload. Every field in <code>$payload<\/code>, <code>account_id<\/code>, <code>account_type<\/code>, <code>event<\/code>, <code>chat_id<\/code>, <code>message_id<\/code>, <code>message<\/code> and <code>sender.attendee_provider_id<\/code>, matches the JSON Unipile documents for the messaging webhook.<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-laravel\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-laravel { background: transparent !important; }\n#upl-wpp-laravel *, #upl-wpp-laravel *::before, #upl-wpp-laravel *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-laravel br { display: none !important; }\n#upl-wpp-laravel p { display: contents !important; }\n#upl-wpp-laravel { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-laravel .wpl-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-laravel .wpl-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(221,223,76,0.18) !important; color: #8a8c2e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-laravel .wpl-badge-dot { width: 7px !important; height: 7px !important; background: #DDDF4C !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-laravel h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-laravel .wpl-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 32px !important; }\n#upl-wpp-laravel .wpl-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-laravel .wpl-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-laravel .wpl-block { margin-bottom: 22px !important; }\n#upl-wpp-laravel .wpl-block-title { display: flex !important; align-items: baseline !important; gap: 10px !important; margin-bottom: 10px !important; flex-wrap: wrap !important; }\n#upl-wpp-laravel .wpl-block-num { font-family: 'Poppins', sans-serif !important; font-size: 0.9rem !important; font-weight: 700 !important; color: #0f2736 !important; }\n#upl-wpp-laravel .wpl-block-desc { font-size: 0.86rem !important; color: #64748b !important; }\n#upl-wpp-laravel .wpl-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-laravel .wpl-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-laravel .wpl-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-laravel .wpl-dot-r { background: #ff5f57 !important; } #upl-wpp-laravel .wpl-dot-y { background: #febc2e !important; } #upl-wpp-laravel .wpl-dot-g { background: #28c840 !important; }\n#upl-wpp-laravel .wpl-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-laravel .wpl-pre { padding: 16px 18px !important; font-size: 12.4px !important; line-height: 1.72 !important; overflow-x: auto !important; }\n#upl-wpp-laravel .wpl-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-laravel .wpl-c { color: #8b949e !important; }\n#upl-wpp-laravel .wpl-k { color: #ff7b72 !important; }\n#upl-wpp-laravel .wpl-fn { color: #d2a8ff !important; }\n#upl-wpp-laravel .wpl-s { color: #a5d6ff !important; }\n#upl-wpp-laravel .wpl-w { color: #e6edf3 !important; }\n#upl-wpp-laravel .wpl-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; margin-top: 8px !important; margin-bottom: 26px !important; }\n#upl-wpp-laravel .wpl-outro a { color: #2aaa7e !important; text-decoration: underline !important; }\n#upl-wpp-laravel .wpl-cta { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: #DDDF4C !important; color: #0f2736 !important; padding: 14px 28px !important; border-radius: 8px !important; font-size: 0.95rem !important; font-weight: 600 !important; border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-laravel .wpl-cta:hover { transform: translateY(-5px) !important; }\n#upl-wpp-laravel .wpl-cta svg { width: 16px !important; height: 16px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n@media (max-width: 900px) { #upl-wpp-laravel h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-laravel { padding: 40px 16px !important; }\n  #upl-wpp-laravel h2 { font-size: 26px !important; }\n  #upl-wpp-laravel .wpl-lead, #upl-wpp-laravel .wpl-outro { font-size: 15px !important; }\n  #upl-wpp-laravel .wpl-pre { font-size: 10.8px !important; padding: 12px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-laravel\">\n  <div class=\"wpl-container\">\n    <div class=\"wpl-badge\"><span class=\"wpl-badge-dot\"><\/span><span>Production<\/span><\/div>\n    <h2>How do you integrate the WhatsApp API into a Laravel application?<\/h2>\n    <div class=\"wpl-lead\">Laravel replaces three things from the plain-PHP examples above: the <code>Http<\/code> facade instead of a hand-rolled Guzzle client, a queued job instead of inline processing, and a route plus controller instead of parsing <code>php:\/\/input<\/code> by hand. The WhatsApp calls underneath are identical to every example already in this guide.<\/div>\n<div class=\"wpl-block\">\n      <div class=\"wpl-block-title\"><span class=\"wpl-block-num\">1. Configuration<\/span><span class=\"wpl-block-desc\">One entry in services.php, values from .env<\/span><\/div>\n      <div class=\"wpl-code-wrapper\">\n        <div class=\"wpl-editor-bar\"><span class=\"wpl-dot wpl-dot-r\"><\/span><span class=\"wpl-dot wpl-dot-y\"><\/span><span class=\"wpl-dot wpl-dot-g\"><\/span><span class=\"wpl-filename\">config\/services.php<\/span><\/div>\n        <div class=\"wpl-pre\"><code><span class=\"wpl-k\">return<\/span><span class=\"wpl-w\"> [<\/span>&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-c\">\/\/ ...existing services<\/span>&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-s\">'unipile'<\/span><span class=\"wpl-w\"> => [<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-s\">'base_uri'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-fn\">env<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'UNIPILE_BASE_URI'<\/span><span class=\"wpl-w\">, <\/span><span class=\"wpl-s\">'https:\/\/api1.unipile.com:13111'<\/span><span class=\"wpl-w\">),<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-s\">'api_key'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-fn\">env<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'UNIPILE_API_KEY'<\/span><span class=\"wpl-w\">),<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-s\">'webhook_secret'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-fn\">env<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'UNIPILE_WEBHOOK_SECRET'<\/span><span class=\"wpl-w\">),<\/span>&#10;<span class=\"wpl-w\">    ],<\/span>&#10;<span class=\"wpl-w\">];<\/span><\/code><\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpl-block\">\n      <div class=\"wpl-block-title\"><span class=\"wpl-block-num\">2. A thin service class over the Http facade<\/span><\/div>\n      <div class=\"wpl-code-wrapper\">\n        <div class=\"wpl-editor-bar\"><span class=\"wpl-dot wpl-dot-r\"><\/span><span class=\"wpl-dot wpl-dot-y\"><\/span><span class=\"wpl-dot wpl-dot-g\"><\/span><span class=\"wpl-filename\">app\/Services\/WhatsappService.php<\/span><\/div>\n        <div class=\"wpl-pre\"><code><span class=\"wpl-k\">namespace<\/span><span class=\"wpl-w\"> App\\Services;<\/span>&#10;&#10;<span class=\"wpl-k\">use<\/span><span class=\"wpl-w\"> Illuminate\\Support\\Facades\\Http;<\/span>&#10;&#10;<span class=\"wpl-k\">class<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">WhatsappService<\/span>&#10;<span class=\"wpl-w\">{<\/span>&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">protected<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">function<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">client<\/span><span class=\"wpl-w\">()<\/span>&#10;<span class=\"wpl-w\">    {<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-k\">return<\/span><span class=\"wpl-w\"> Http::<\/span><span class=\"wpl-fn\">baseUrl<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-fn\">config<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'services.unipile.base_uri'<\/span><span class=\"wpl-w\">))<\/span>&#10;<span class=\"wpl-w\">            -><\/span><span class=\"wpl-fn\">withHeaders<\/span><span class=\"wpl-w\">([<\/span><span class=\"wpl-s\">'X-API-KEY'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-fn\">config<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'services.unipile.api_key'<\/span><span class=\"wpl-w\">)]);<\/span>&#10;<span class=\"wpl-w\">    }<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">public<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">function<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">sendMessage<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-k\">string<\/span><span class=\"wpl-w\"> $chatId, <\/span><span class=\"wpl-k\">string<\/span><span class=\"wpl-w\"> $text): <\/span><span class=\"wpl-k\">array<\/span>&#10;<span class=\"wpl-w\">    {<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-k\">return<\/span><span class=\"wpl-w\"> $this-><\/span><span class=\"wpl-fn\">client<\/span><span class=\"wpl-w\">()<\/span>&#10;<span class=\"wpl-w\">            -><\/span><span class=\"wpl-fn\">asMultipart<\/span><span class=\"wpl-w\">()<\/span>&#10;<span class=\"wpl-w\">            -><\/span><span class=\"wpl-fn\">post<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">\"\/api\/v1\/chats\/{$chatId}\/messages\"<\/span><span class=\"wpl-w\">, [<\/span>&#10;<span class=\"wpl-w\">                [<\/span><span class=\"wpl-s\">'name'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-s\">'text'<\/span><span class=\"wpl-w\">, <\/span><span class=\"wpl-s\">'contents'<\/span><span class=\"wpl-w\"> => $text],<\/span>&#10;<span class=\"wpl-w\">            ])<\/span>&#10;<span class=\"wpl-w\">            -><\/span><span class=\"wpl-fn\">json<\/span><span class=\"wpl-w\">();<\/span>&#10;<span class=\"wpl-w\">    }<\/span>&#10;<span class=\"wpl-w\">}<\/span><\/code><\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpl-block\">\n      <div class=\"wpl-block-title\"><span class=\"wpl-block-num\">3. Route and webhook controller<\/span><\/div>\n      <div class=\"wpl-code-wrapper\">\n        <div class=\"wpl-editor-bar\"><span class=\"wpl-dot wpl-dot-r\"><\/span><span class=\"wpl-dot wpl-dot-y\"><\/span><span class=\"wpl-dot wpl-dot-g\"><\/span><span class=\"wpl-filename\">routes\/api.php<\/span><\/div>\n        <div class=\"wpl-pre\"><code><span class=\"wpl-w\">Route::<\/span><span class=\"wpl-fn\">post<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'\/webhooks\/whatsapp'<\/span><span class=\"wpl-w\">, [WhatsappWebhookController::<\/span><span class=\"wpl-k\">class<\/span><span class=\"wpl-w\">, <\/span><span class=\"wpl-s\">'handle'<\/span><span class=\"wpl-w\">]);<\/span><\/code><\/div>\n      <\/div>\n      <div class=\"wpl-code-wrapper\" style=\"margin-top:10px;\">\n        <div class=\"wpl-editor-bar\"><span class=\"wpl-dot wpl-dot-r\"><\/span><span class=\"wpl-dot wpl-dot-y\"><\/span><span class=\"wpl-dot wpl-dot-g\"><\/span><span class=\"wpl-filename\">app\/Http\/Controllers\/WhatsappWebhookController.php<\/span><\/div>\n        <div class=\"wpl-pre\"><code><span class=\"wpl-k\">public<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">function<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">handle<\/span><span class=\"wpl-w\">(Request $request)<\/span>&#10;<span class=\"wpl-w\">{<\/span>&#10;<span class=\"wpl-w\">    $provided = $request-><\/span><span class=\"wpl-fn\">header<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'X-Webhook-Secret'<\/span><span class=\"wpl-w\">, <\/span><span class=\"wpl-s\">''<\/span><span class=\"wpl-w\">);<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">if<\/span><span class=\"wpl-w\"> (!<\/span><span class=\"wpl-fn\">hash_equals<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-fn\">config<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'services.unipile.webhook_secret'<\/span><span class=\"wpl-w\">), $provided)) {<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-fn\">abort<\/span><span class=\"wpl-w\">(401);<\/span>&#10;<span class=\"wpl-w\">    }<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">if<\/span><span class=\"wpl-w\"> ($request-><\/span><span class=\"wpl-fn\">input<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-s\">'event'<\/span><span class=\"wpl-w\">) === <\/span><span class=\"wpl-s\">'message_received'<\/span><span class=\"wpl-w\">) {<\/span>&#10;<span class=\"wpl-w\">        ProcessWhatsappMessage::<\/span><span class=\"wpl-fn\">dispatch<\/span><span class=\"wpl-w\">($request-><\/span><span class=\"wpl-fn\">all<\/span><span class=\"wpl-w\">());<\/span>&#10;<span class=\"wpl-w\">    }<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">return<\/span><span class=\"wpl-w\"> response()-><\/span><span class=\"wpl-fn\">json<\/span><span class=\"wpl-w\">([<\/span><span class=\"wpl-s\">'status'<\/span><span class=\"wpl-w\"> => <\/span><span class=\"wpl-s\">'received'<\/span><span class=\"wpl-w\">]);<\/span>&#10;<span class=\"wpl-w\">}<\/span><\/code><\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpl-block\">\n      <div class=\"wpl-block-title\"><span class=\"wpl-block-num\">4. A queued job, so the webhook route stays fast<\/span><\/div>\n      <div class=\"wpl-code-wrapper\">\n        <div class=\"wpl-editor-bar\"><span class=\"wpl-dot wpl-dot-r\"><\/span><span class=\"wpl-dot wpl-dot-y\"><\/span><span class=\"wpl-dot wpl-dot-g\"><\/span><span class=\"wpl-filename\">app\/Jobs\/ProcessWhatsappMessage.php<\/span><\/div>\n        <div class=\"wpl-pre\"><code><span class=\"wpl-k\">class<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">ProcessWhatsappMessage<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">implements<\/span><span class=\"wpl-w\"> ShouldQueue<\/span>&#10;<span class=\"wpl-w\">{<\/span>&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">use<\/span><span class=\"wpl-w\"> Dispatchable, InteractsWithQueue, Queueable, SerializesModels;<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">public<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">function<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">__construct<\/span><span class=\"wpl-w\">(<\/span><span class=\"wpl-k\">public<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">array<\/span><span class=\"wpl-w\"> $payload) {}<\/span>&#10;&#10;<span class=\"wpl-w\">    <\/span><span class=\"wpl-k\">public<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-k\">function<\/span><span class=\"wpl-w\"> <\/span><span class=\"wpl-fn\">handle<\/span><span class=\"wpl-w\">(): <\/span><span class=\"wpl-k\">void<\/span>&#10;<span class=\"wpl-w\">    {<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-c\">\/\/ look up the tenant by $this->payload['account_id'],<\/span>&#10;<span class=\"wpl-w\">        <\/span><span class=\"wpl-c\">\/\/ store the message, notify the right user<\/span>&#10;<span class=\"wpl-w\">    }<\/span>&#10;<span class=\"wpl-w\">}<\/span><\/code><\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpl-outro\">The route never touches Guzzle directly, it goes through <code>WhatsappService<\/code>, which makes the WhatsApp calls mockable in tests the same way any other Laravel HTTP integration is. See <a href=\"https:\/\/laravel.com\/docs\/http-client\" target=\"_blank\" rel=\"noopener\">Laravel's HTTP client documentation<\/a> for faking these requests in your test suite.<\/div>\n<a class=\"wpl-cta\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n      <span>Build it in Laravel<\/span>\n      <svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n    <\/a>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-laravel');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      e.preventDefault();\n      e.stopPropagation();\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-groups\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-groups { background: transparent !important; }\n#upl-wpp-groups *, #upl-wpp-groups *::before, #upl-wpp-groups *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-groups br { display: none !important; }\n#upl-wpp-groups p { display: contents !important; }\n#upl-wpp-groups { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-groups .wpg-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-groups .wpg-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(221,223,76,0.18) !important; color: #8a8c2e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-groups .wpg-badge-dot { width: 7px !important; height: 7px !important; background: #DDDF4C !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-groups h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-groups .wpg-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 28px !important; }\n#upl-wpp-groups .wpg-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-groups .wpg-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-groups .wpg-cols { display: grid !important; grid-template-columns: 1fr 1fr !important; gap: 20px !important; margin-bottom: 24px !important; }\n#upl-wpp-groups .wpg-col-title { font-size: 0.86rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 10px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-groups .wpg-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-groups .wpg-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-groups .wpg-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-groups .wpg-dot-r { background: #ff5f57 !important; } #upl-wpp-groups .wpg-dot-y { background: #febc2e !important; } #upl-wpp-groups .wpg-dot-g { background: #28c840 !important; }\n#upl-wpp-groups .wpg-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-groups .wpg-pre { padding: 16px 18px !important; font-size: 12.4px !important; line-height: 1.72 !important; overflow-x: auto !important; }\n#upl-wpp-groups .wpg-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-groups .wpg-c { color: #8b949e !important; }\n#upl-wpp-groups .wpg-k { color: #ff7b72 !important; }\n#upl-wpp-groups .wpg-fn { color: #d2a8ff !important; }\n#upl-wpp-groups .wpg-s { color: #a5d6ff !important; }\n#upl-wpp-groups .wpg-w { color: #e6edf3 !important; }\n#upl-wpp-groups .wpg-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; margin-bottom: 26px !important; }\n#upl-wpp-groups .wpg-outro a { color: #2aaa7e !important; text-decoration: underline !important; }\n#upl-wpp-groups .wpg-cta { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: #DDDF4C !important; color: #0f2736 !important; padding: 13px 26px !important; border-radius: 8px !important; font-size: 0.92rem !important; font-weight: 600 !important; border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-groups .wpg-cta:hover { transform: translateY(-5px) !important; }\n#upl-wpp-groups .wpg-cta svg { width: 15px !important; height: 15px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n@media (max-width: 900px) {\n  #upl-wpp-groups h2 { font-size: 28px !important; }\n  #upl-wpp-groups .wpg-cols { grid-template-columns: 1fr !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-groups { padding: 40px 16px !important; }\n  #upl-wpp-groups h2 { font-size: 26px !important; }\n  #upl-wpp-groups .wpg-lead, #upl-wpp-groups .wpg-outro { font-size: 15px !important; }\n  #upl-wpp-groups .wpg-pre { font-size: 11px !important; padding: 12px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-groups\">\n  <div class=\"wpg-container\">\n    <div class=\"wpg-badge\"><span class=\"wpg-badge-dot\"><\/span><span>Production<\/span><\/div>\n    <h2>How do you manage WhatsApp groups from PHP?<\/h2>\n    <div class=\"wpg-lead\">Managing a WhatsApp group from PHP is a single <code>PATCH<\/code> call to the chat endpoint with an <code>action<\/code> field: <code>addParticipant<\/code>, <code>removeParticipant<\/code>, or <code>getInviteLink<\/code>. Meta's own Cloud API groups feature caps a group at <strong>8 participants<\/strong> and exposes no endpoint to add someone directly, only an invite link to share.<\/div>\n<div class=\"wpg-cols\">\n      <div>\n        <div class=\"wpg-col-title\">Add a participant<\/div>\n        <div class=\"wpg-code-wrapper\">\n          <div class=\"wpg-editor-bar\"><span class=\"wpg-dot wpg-dot-r\"><\/span><span class=\"wpg-dot wpg-dot-y\"><\/span><span class=\"wpg-dot wpg-dot-g\"><\/span><span class=\"wpg-filename\">add-participant.php<\/span><\/div>\n          <div class=\"wpg-pre\"><code><span class=\"wpg-w\">$client-><\/span><span class=\"wpg-fn\">patch<\/span><span class=\"wpg-w\">(<\/span><span class=\"wpg-s\">\"\/api\/v1\/chats\/{$groupChatId}\"<\/span><span class=\"wpg-w\">, [<\/span>&#10;<span class=\"wpg-w\">    'json' => [<\/span>&#10;<span class=\"wpg-w\">        'action' => <\/span><span class=\"wpg-s\">'addParticipant'<\/span><span class=\"wpg-w\">,<\/span>&#10;<span class=\"wpg-w\">        'value' => <\/span><span class=\"wpg-s\">'33612345678@s.whatsapp.net'<\/span><span class=\"wpg-w\">,<\/span>&#10;<span class=\"wpg-w\">    ],<\/span>&#10;<span class=\"wpg-w\">]);<\/span><\/code><\/div>\n        <\/div>\n      <\/div>\n      <div>\n        <div class=\"wpg-col-title\">Get the invite link<\/div>\n        <div class=\"wpg-code-wrapper\">\n          <div class=\"wpg-editor-bar\"><span class=\"wpg-dot wpg-dot-r\"><\/span><span class=\"wpg-dot wpg-dot-y\"><\/span><span class=\"wpg-dot wpg-dot-g\"><\/span><span class=\"wpg-filename\">invite-link.php<\/span><\/div>\n          <div class=\"wpg-pre\"><code><span class=\"wpg-w\">$res = $client-><\/span><span class=\"wpg-fn\">patch<\/span><span class=\"wpg-w\">(<\/span><span class=\"wpg-s\">\"\/api\/v1\/chats\/{$groupChatId}\"<\/span><span class=\"wpg-w\">, [<\/span>&#10;<span class=\"wpg-w\">    'json' => ['action' => <\/span><span class=\"wpg-s\">'getInviteLink'<\/span><span class=\"wpg-w\">],<\/span>&#10;<span class=\"wpg-w\">]);<\/span>&#10;&#10;<span class=\"wpg-w\">$link = <\/span><span class=\"wpg-fn\">json_decode<\/span><span class=\"wpg-w\">($res-><\/span><span class=\"wpg-fn\">getBody<\/span><span class=\"wpg-w\">()-><\/span><span class=\"wpg-fn\">getContents<\/span><span class=\"wpg-w\">(), <\/span><span class=\"wpg-k\">true<\/span><span class=\"wpg-w\">)[<\/span><span class=\"wpg-s\">'invite_link'<\/span><span class=\"wpg-w\">];<\/span><\/code><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n<div class=\"wpg-outro\"><code>removeParticipant<\/code> takes the same shape as <code>addParticipant<\/code>, with the participant's WhatsApp id in <code>value<\/code>. This is the one action Meta's own Groups API does not expose at all, adding someone happens only through the invite link on their side. For every limit, the 10,000-groups-per-number ceiling and what still is not supported, see the <a href=\"https:\/\/www.unipile.com\/whatsapp-group-api\/\">WhatsApp Group API<\/a> reference.<\/div>\n    <a class=\"wpg-cta\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n      <span>Build group management<\/span>\n      <svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n    <\/a>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-groups');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      e.preventDefault();\n      e.stopPropagation();\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-tenant\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-tenant { background: transparent !important; }\n#upl-wpp-tenant *, #upl-wpp-tenant *::before, #upl-wpp-tenant *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-tenant br { display: none !important; }\n#upl-wpp-tenant p { display: contents !important; }\n#upl-wpp-tenant { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-tenant .wpm-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-tenant .wpm-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-tenant .wpm-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-tenant h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-tenant .wpm-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 26px !important; }\n#upl-wpp-tenant .wpm-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-tenant .wpm-lead code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.88em !important; color: #0f2736 !important; }\n#upl-wpp-tenant .wpm-code-wrapper { border-radius: 12px !important; overflow: hidden !important; background: #0d1117 !important; margin-bottom: 22px !important; }\n#upl-wpp-tenant .wpm-editor-bar { background: #161b22 !important; padding: 10px 16px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-tenant .wpm-dot { width: 10px !important; height: 10px !important; border-radius: 50% !important; display: inline-block !important; }\n#upl-wpp-tenant .wpm-dot-r { background: #ff5f57 !important; } #upl-wpp-tenant .wpm-dot-y { background: #febc2e !important; } #upl-wpp-tenant .wpm-dot-g { background: #28c840 !important; }\n#upl-wpp-tenant .wpm-filename { color: #8b949e !important; font-size: 12px !important; margin-left: 4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-tenant .wpm-pre { padding: 16px 18px !important; font-size: 12.6px !important; line-height: 1.72 !important; overflow-x: auto !important; }\n#upl-wpp-tenant .wpm-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-tenant .wpm-c { color: #8b949e !important; }\n#upl-wpp-tenant .wpm-k { color: #ff7b72 !important; }\n#upl-wpp-tenant .wpm-fn { color: #d2a8ff !important; }\n#upl-wpp-tenant .wpm-s { color: #a5d6ff !important; }\n#upl-wpp-tenant .wpm-w { color: #e6edf3 !important; }\n#upl-wpp-tenant .wpm-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; }\n#upl-wpp-tenant .wpm-outro strong { color: #0f2736 !important; font-weight: 700 !important; }\n@media (max-width: 900px) { #upl-wpp-tenant h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-tenant { padding: 40px 16px !important; }\n  #upl-wpp-tenant h2 { font-size: 26px !important; }\n  #upl-wpp-tenant .wpm-lead, #upl-wpp-tenant .wpm-outro { font-size: 15px !important; }\n  #upl-wpp-tenant .wpm-pre { font-size: 11px !important; padding: 12px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-tenant\">\n  <div class=\"wpm-container\">\n    <div class=\"wpm-badge\"><span class=\"wpm-badge-dot\"><\/span><span>Scale<\/span><\/div>\n    <h2>How do you handle many user accounts from one PHP application?<\/h2>\n    <div class=\"wpm-lead\">A PHP SaaS product does not have one WhatsApp account, it has one per customer. There is a single Unipile <code>X-API-KEY<\/code> for your whole application, but a distinct <code>account_id<\/code> for every end user who links their WhatsApp. The pattern is to store that <code>account_id<\/code> next to your own tenant row, and pass it explicitly on every call that could otherwise cross accounts.<\/div>\n<div class=\"wpm-code-wrapper\">\n      <div class=\"wpm-editor-bar\"><span class=\"wpm-dot wpm-dot-r\"><\/span><span class=\"wpm-dot wpm-dot-y\"><\/span><span class=\"wpm-dot wpm-dot-g\"><\/span><span class=\"wpm-filename\">route-by-tenant.php<\/span><\/div>\n      <div class=\"wpm-pre\"><code><span class=\"wpm-c\">\/\/ Inside the webhook handler: find which tenant this<\/span>&#10;<span class=\"wpm-c\">\/\/ message belongs to before doing anything with it.<\/span>&#10;<span class=\"wpm-w\">$stmt = $pdo-><\/span><span class=\"wpm-fn\">prepare<\/span><span class=\"wpm-w\">(<\/span><span class=\"wpm-s\">'SELECT id FROM tenants WHERE unipile_account_id = ?'<\/span><span class=\"wpm-w\">);<\/span>&#10;<span class=\"wpm-w\">$stmt-><\/span><span class=\"wpm-fn\">execute<\/span><span class=\"wpm-w\">([$payload[<\/span><span class=\"wpm-s\">'account_id'<\/span><span class=\"wpm-w\">]]);<\/span>&#10;<span class=\"wpm-w\">$tenantId = $stmt-><\/span><span class=\"wpm-fn\">fetchColumn<\/span><span class=\"wpm-w\">();<\/span>&#10;&#10;<span class=\"wpm-k\">if<\/span><span class=\"wpm-w\"> ($tenantId === <\/span><span class=\"wpm-k\">false<\/span><span class=\"wpm-w\">) {<\/span>&#10;<span class=\"wpm-w\">    <\/span><span class=\"wpm-c\">\/\/ unknown account_id, reject rather than guess the tenant<\/span>&#10;<span class=\"wpm-w\">    <\/span><span class=\"wpm-fn\">http_response_code<\/span><span class=\"wpm-w\">(404);<\/span>&#10;<span class=\"wpm-w\">    <\/span><span class=\"wpm-k\">exit<\/span><span class=\"wpm-w\">;<\/span>&#10;<span class=\"wpm-w\">}<\/span>&#10;&#10;<span class=\"wpm-c\">\/\/ Outbound: pass account_id so a stale or reused chat_id can<\/span>&#10;<span class=\"wpm-c\">\/\/ never send through the wrong tenant's WhatsApp number.<\/span>&#10;<span class=\"wpm-w\">$client-><\/span><span class=\"wpm-fn\">post<\/span><span class=\"wpm-w\">(<\/span><span class=\"wpm-s\">\"\/api\/v1\/chats\/{$chatId}\/messages\"<\/span><span class=\"wpm-w\">, [<\/span>&#10;<span class=\"wpm-w\">    'multipart' => [<\/span>&#10;<span class=\"wpm-w\">        [<\/span><span class=\"wpm-s\">'name'<\/span><span class=\"wpm-w\"> => <\/span><span class=\"wpm-s\">'text'<\/span><span class=\"wpm-w\">, <\/span><span class=\"wpm-s\">'contents'<\/span><span class=\"wpm-w\"> => $text],<\/span>&#10;<span class=\"wpm-w\">        [<\/span><span class=\"wpm-s\">'name'<\/span><span class=\"wpm-w\"> => <\/span><span class=\"wpm-s\">'account_id'<\/span><span class=\"wpm-w\">, <\/span><span class=\"wpm-s\">'contents'<\/span><span class=\"wpm-w\"> => $expectedAccountId],<\/span>&#10;<span class=\"wpm-w\">    ],<\/span>&#10;<span class=\"wpm-w\">]);<\/span><\/code><\/div>\n    <\/div>\n<div class=\"wpm-outro\">The optional <code>account_id<\/code> field on the messages endpoint exists specifically to prevent sending in a chat outside that account, treat it as mandatory in a multi-tenant codebase even though the API does not require it. Encrypt the stored <code>account_id<\/code> values at rest like any other customer credential: they are not secret on their own, but they are the join key between your users table and someone's real WhatsApp conversations.<\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-mistakes\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-mistakes { background: transparent !important; }\n#upl-wpp-mistakes *, #upl-wpp-mistakes *::before, #upl-wpp-mistakes *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-mistakes br { display: none !important; }\n#upl-wpp-mistakes p { display: contents !important; }\n#upl-wpp-mistakes { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-mistakes .wpx-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-mistakes .wpx-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(221,223,76,0.18) !important; color: #8a8c2e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-mistakes .wpx-badge-dot { width: 7px !important; height: 7px !important; background: #DDDF4C !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-mistakes h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-mistakes .wpx-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 30px !important; }\n#upl-wpp-mistakes .wpx-list { display: flex !important; flex-direction: column !important; gap: 16px !important; margin-bottom: 24px !important; }\n#upl-wpp-mistakes .wpx-item { display: grid !important; grid-template-columns: 40px 1fr !important; gap: 16px !important; padding: 20px !important; background: #ffffff !important; border: 1px solid #e5e7eb !important; border-radius: 12px !important; }\n#upl-wpp-mistakes .wpx-item-icon { width: 40px !important; height: 40px !important; background: rgba(239,68,68,0.1) !important; border-radius: 10px !important; display: flex !important; align-items: center !important; justify-content: center !important; }\n#upl-wpp-mistakes .wpx-item-icon svg { width: 18px !important; height: 18px !important; stroke: #dc2626 !important; fill: none !important; stroke-width: 2.2 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-mistakes .wpx-item-title { font-size: 0.98rem !important; font-weight: 700 !important; color: #0f2736 !important; margin-bottom: 6px !important; font-family: 'Poppins', sans-serif !important; }\n#upl-wpp-mistakes .wpx-item-desc { font-size: 0.9rem !important; line-height: 1.7 !important; color: #4a5568 !important; }\n#upl-wpp-mistakes .wpx-item-desc code { font-family: 'Courier New', monospace !important; background: #f1f5f9 !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #0f2736 !important; }\n#upl-wpp-mistakes .wpx-item-desc strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-mistakes .wpx-fix { margin-top: 12px !important; border-radius: 10px !important; overflow: hidden !important; background: #0d1117 !important; }\n#upl-wpp-mistakes .wpx-fix-bar { background: #161b22 !important; padding: 8px 14px !important; display: flex !important; align-items: center !important; gap: 8px !important; }\n#upl-wpp-mistakes .wpx-fix-label { color: #3BB98B !important; font-size: 11px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.4px !important; font-family: 'Courier New', monospace !important; }\n#upl-wpp-mistakes .wpx-fix-pre { padding: 14px 16px !important; font-size: 12.2px !important; line-height: 1.7 !important; overflow-x: auto !important; }\n#upl-wpp-mistakes .wpx-fix-pre code { font-family: 'Courier New', monospace !important; white-space: pre !important; display: block !important; }\n#upl-wpp-mistakes .wpx-c { color: #8b949e !important; }\n#upl-wpp-mistakes .wpx-k { color: #ff7b72 !important; }\n#upl-wpp-mistakes .wpx-fn { color: #d2a8ff !important; }\n#upl-wpp-mistakes .wpx-s { color: #a5d6ff !important; }\n#upl-wpp-mistakes .wpx-w { color: #e6edf3 !important; }\n@media (max-width: 900px) { #upl-wpp-mistakes h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-mistakes { padding: 40px 16px !important; }\n  #upl-wpp-mistakes h2 { font-size: 26px !important; }\n  #upl-wpp-mistakes .wpx-lead { font-size: 15px !important; }\n  #upl-wpp-mistakes .wpx-item { grid-template-columns: 1fr !important; }\n  #upl-wpp-mistakes .wpx-fix-pre { font-size: 10.8px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-mistakes\">\n  <div class=\"wpx-container\">\n    <div class=\"wpx-badge\"><span class=\"wpx-badge-dot\"><\/span><span>Pitfalls<\/span><\/div>\n    <h2>What are the most common PHP-specific mistakes?<\/h2>\n    <div class=\"wpx-lead\">Most WhatsApp API bugs in a PHP codebase come from PHP itself, not from the API. These five show up repeatedly in production integrations.<\/div>\n<div class=\"wpx-list\">\n      <div class=\"wpx-item\">\n        <div class=\"wpx-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"\/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"\/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpx-item-title\">Truncating a message with substr() instead of mb_substr()<\/div>\n          <div class=\"wpx-item-desc\">PHP's <code>substr()<\/code> counts bytes, not characters. An emoji is a multi-byte UTF-8 sequence, cut it in half and you send a broken character or invalid JSON. Always use the multi-byte functions on user-generated WhatsApp text.<\/div>\n          <div class=\"wpx-fix\">\n            <div class=\"wpx-fix-bar\"><span class=\"wpx-fix-label\">Fix<\/span><\/div>\n            <div class=\"wpx-fix-pre\"><code><span class=\"wpx-w\">$safe = <\/span><span class=\"wpx-fn\">mb_substr<\/span><span class=\"wpx-w\">($text, 0, 4096, <\/span><span class=\"wpx-s\">'UTF-8'<\/span><span class=\"wpx-w\">);<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpx-item\">\n        <div class=\"wpx-item-icon\"><svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpx-item-title\">cURL error 60 on Windows and XAMPP<\/div>\n          <div class=\"wpx-item-desc\">\"SSL certificate problem: unable to get local issuer certificate.\" Windows PHP builds and XAMPP often ship without a current CA bundle wired into php.ini, so Guzzle's HTTPS calls fail even though the code is correct.<\/div>\n          <div class=\"wpx-fix\">\n            <div class=\"wpx-fix-bar\"><span class=\"wpx-fix-label\">Fix, php.ini<\/span><\/div>\n            <div class=\"wpx-fix-pre\"><code><span class=\"wpx-w\">curl.cainfo = <\/span><span class=\"wpx-s\">\"C:\\php\\extras\\cacert.pem\"<\/span>&#10;<span class=\"wpx-w\">openssl.cafile = <\/span><span class=\"wpx-s\">\"C:\\php\\extras\\cacert.pem\"<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpx-item\">\n        <div class=\"wpx-item-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><polyline points=\"12 6 12 12 16 14\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpx-item-title\">max_execution_time killing the webhook before it answers<\/div>\n          <div class=\"wpx-item-desc\">A default of 30 seconds is plenty until the handler makes a slow outbound call before responding. If Unipile does not get a fast response, it retries, and a slow handler starts processing the same message twice. Respond first, work second, as shown in the webhook section above.<\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpx-item\">\n        <div class=\"wpx-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M23 4v6h-6\"\/><path d=\"M1 20v-6h6\"\/><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpx-item-title\">No backoff on 429 or 5xx responses<\/div>\n          <div class=\"wpx-item-desc\">A tight <code>while<\/code> loop that retries immediately on failure turns one rate limit into a self-inflicted outage. Wait, and increase the wait on every consecutive failure.<\/div>\n          <div class=\"wpx-fix\">\n            <div class=\"wpx-fix-bar\"><span class=\"wpx-fix-label\">Fix<\/span><\/div>\n            <div class=\"wpx-fix-pre\"><code><span class=\"wpx-k\">for<\/span><span class=\"wpx-w\"> ($attempt = 1; $attempt <= 5; $attempt++) {<\/span>&#10;<span class=\"wpx-w\">    <\/span><span class=\"wpx-k\">try<\/span><span class=\"wpx-w\"> {<\/span>&#10;<span class=\"wpx-w\">        <\/span><span class=\"wpx-k\">return<\/span><span class=\"wpx-w\"> $client-><\/span><span class=\"wpx-fn\">post<\/span><span class=\"wpx-w\">($uri, $options);<\/span>&#10;<span class=\"wpx-w\">    } <\/span><span class=\"wpx-k\">catch<\/span><span class=\"wpx-w\"> (ConnectException | ServerException $e) {<\/span>&#10;<span class=\"wpx-w\">        <\/span><span class=\"wpx-fn\">usleep<\/span><span class=\"wpx-w\">((2 ** $attempt) * 100_000);<\/span><span class=\"wpx-c\"> \/\/ 0.2s, 0.4s, 0.8s...<\/span>&#10;<span class=\"wpx-w\">    }<\/span>&#10;<span class=\"wpx-w\">}<\/span><\/code><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n<div class=\"wpx-item\">\n        <div class=\"wpx-item-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M3 3v18h18\"\/><path d=\"M18.7 8l-5.1 5.2-2.8-2.7L7 14.3\"\/><\/svg><\/div>\n        <div>\n          <div class=\"wpx-item-title\">Logging the raw response and calling it debugging<\/div>\n          <div class=\"wpx-item-desc\">If you build a JSON body by hand instead of letting Guzzle's <code>json<\/code> option handle it, add <code>JSON_UNESCAPED_UNICODE<\/code> to <code>json_encode()<\/code>. Without it, emoji and accented names show up as escaped <code>\\u<\/code> sequences in your logs, which is technically valid JSON but unreadable when you are trying to debug a real conversation.<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<span id=\"wpp-cost\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-cost { background: transparent !important; }\n#upl-wpp-cost *, #upl-wpp-cost *::before, #upl-wpp-cost *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-cost br { display: none !important; }\n#upl-wpp-cost p { display: contents !important; }\n#upl-wpp-cost { padding: 50px 20px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-cost .wpc-container { max-width: 1100px !important; margin: 0 auto !important; }\n#upl-wpp-cost .wpc-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.12) !important; color: #2aaa7e !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 20px !important; }\n#upl-wpp-cost .wpc-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-cost h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #0f2736 !important; line-height: 1.25 !important; margin-bottom: 20px !important; }\n#upl-wpp-cost .wpc-lead { font-size: 17px !important; line-height: 1.8 !important; color: #1e293b !important; margin-bottom: 24px !important; }\n#upl-wpp-cost .wpc-lead strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-cost .wpc-list { display: flex !important; flex-direction: column !important; gap: 10px !important; margin-bottom: 26px !important; }\n#upl-wpp-cost .wpc-list-item { display: flex !important; align-items: flex-start !important; gap: 10px !important; font-size: 0.94rem !important; line-height: 1.6 !important; color: #383838 !important; }\n#upl-wpp-cost .wpc-list-item svg { width: 16px !important; height: 16px !important; min-width: 16px !important; stroke: #3BB98B !important; fill: none !important; stroke-width: 2.4 !important; stroke-linecap: round !important; stroke-linejoin: round !important; margin-top: 3px !important; }\n#upl-wpp-cost .wpc-list-item strong { color: #0f2736 !important; font-weight: 700 !important; }\n#upl-wpp-cost .wpc-outro { font-size: 16px !important; line-height: 1.8 !important; color: #383838 !important; }\n#upl-wpp-cost .wpc-outro a { color: #2aaa7e !important; text-decoration: underline !important; }\n@media (max-width: 900px) { #upl-wpp-cost h2 { font-size: 28px !important; } }\n@media (max-width: 600px) {\n  #upl-wpp-cost { padding: 40px 16px !important; }\n  #upl-wpp-cost h2 { font-size: 26px !important; }\n  #upl-wpp-cost .wpc-lead, #upl-wpp-cost .wpc-outro { font-size: 15px !important; }\n}\n<\/style>\n<div id=\"upl-wpp-cost\">\n  <div class=\"wpc-container\">\n    <div class=\"wpc-badge\"><span class=\"wpc-badge-dot\"><\/span><span>Cost<\/span><\/div>\n    <h2>How much does it cost to send WhatsApp messages from PHP?<\/h2>\n    <div class=\"wpc-lead\">Nothing in the PHP code changes the price. Meta bills <strong>per message since July 1, 2025<\/strong>, not per conversation. The one thing your code controls is timing: a reply sent inside the 24-hour service window after a user's message is still free, the identical call sent an hour later is billable.<\/div>\n<div class=\"wpc-list\">\n      <div class=\"wpc-list-item\"><svg viewBox=\"0 0 24 24\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span><strong>Utility and authentication templates<\/strong> stay free inside an open service window, billed outside it.<\/span><\/div>\n      <div class=\"wpc-list-item\"><svg viewBox=\"0 0 24 24\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span><strong>Marketing templates<\/strong> are billed regardless of the window.<\/span><\/div>\n      <div class=\"wpc-list-item\"><svg viewBox=\"0 0 24 24\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Per-message rates vary by recipient country and message category, not by the client library you send them with.<\/span><\/div>\n    <\/div>\n<div class=\"wpc-outro\">Timestamp every inbound message your PHP webhook receives and keep a per-conversation \"window open until\" value, that is the only input your billing logic actually needs. For current <a href=\"https:\/\/www.unipile.com\/whatsapp-business-api-pricing\/\">per-message WhatsApp pricing<\/a> by country and category, see the full pricing breakdown.<\/div>\n  <\/div>\n<\/div>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@600;700&#038;display=swap\" rel=\"stylesheet\">\n<script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do you integrate the WhatsApp API in PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Create a Guzzle client pointed at the Unipile REST API, call POST \/api\/v1\/accounts with provider WHATSAPP to get a QR code or pairing code, have the user complete it on their phone, then use the same client for GET, POST and PATCH calls to send messages, list chats and manage groups. There is no PHP-specific endpoint, every call is a normal HTTP request with an X-API-KEY header.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can you send a WhatsApp message programmatically with PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. A single POST to \/api\/v1\/chats\/{chat_id}\/messages with a text field in a multipart body sends the message and returns a message_id.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Do you need a Meta Business verification to use WhatsApp with PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Only if you go through Meta's Cloud API directly or a Business Solution Provider built on top of it. Connecting a WhatsApp account through Unipile links the user's existing WhatsApp number by QR code or pairing code and does not require Meta Business verification at all.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Is there an official Unipile PHP SDK?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No actively maintained one. A community package, unipile\/unipile-php-sdk, is listed on Packagist but marked abandoned, with no commit since October 17, 2023. Every example in this guide calls the REST API directly through Guzzle instead.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do you receive WhatsApp messages in PHP without a public server?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"You cannot receive webhooks without a publicly reachable HTTPS URL. During local development, tunnel a local port with a service like ngrok and point the webhook's request_url at the tunnel's address. Polling the messages endpoint is the fallback when a public endpoint genuinely is not possible, at the cost of latency and extra requests.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Does the WhatsApp API work with Laravel?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes, nothing about it is framework-specific. The same calls can be wrapped in the Http facade, a queued job, and a webhook route and controller, which is the idiomatic way to structure it in a Laravel codebase.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can one PHP application manage WhatsApp accounts for multiple end users?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes, that is the normal SaaS shape. One Unipile API key covers the whole application, while every end user gets their own account_id after connecting their WhatsApp. Store that id next to your tenant record and pass it on outbound calls to prevent cross-tenant sends.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do you add someone to a WhatsApp group from PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"PATCH \/api\/v1\/chats\/{chat_id} with action set to addParticipant and value set to the participant's WhatsApp id. Meta's own Cloud API groups feature has no equivalent endpoint, only an invite link.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Why do emoji break in WhatsApp messages sent from PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Almost always because a string was truncated with substr() instead of mb_substr(). PHP's plain string functions count bytes, and an emoji is a multi-byte UTF-8 sequence, cut in the middle it turns into an invalid character or breaks the JSON payload.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Does Guzzle work, or do you need cURL directly?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Guzzle is enough, it is an HTTP client built on top of PHP's cURL extension, not a replacement for it. A raw curl_init() call works identically if a project cannot add the dependency.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How much does sending a WhatsApp message from PHP cost?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"The same as sending it any other way. Meta bills per message since July 1, 2025, based on category and recipient country, not on the client library used to call the API.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Is the 24-hour WhatsApp service window still relevant when using PHP?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. It determines what is free rather than what is technically allowed. A reply inside the 24-hour window after a user's last message ships without being billed as a template message, PHP code that ignores the window simply pays for messages it did not need to.\"\n      }\n    }\n  ]\n}\n<\/script>\n<span id=\"faq-wpp\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<span id=\"wpp-faq\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span>\n<style>\n#upl-wpp-faq { font-family:'Inter',sans-serif; padding:80px 20px; max-width:900px; margin:0 auto; background:transparent!important; }\n#upl-wpp-faq *, #upl-wpp-faq *::before, #upl-wpp-faq *::after { margin:0!important; padding:0!important; box-sizing:border-box!important; }\n#upl-wpp-faq br { display: none !important; }\n#upl-wpp-faq p { display: contents !important; }\n#upl-wpp-faq .upl-faq-header { text-align:center!important; margin-bottom:60px!important; }\n#upl-wpp-faq .upl-faq-title { font-family:'Poppins',sans-serif!important; font-size:clamp(32px,5vw,38px)!important; font-weight:700!important; color:#0f2736!important; margin-bottom:16px!important; line-height:1.2!important; }\n#upl-wpp-faq .upl-faq-subtitle { font-size:17px!important; color:#383838!important; max-width:700px!important; margin:0 auto!important; line-height:1.6!important; }\n#upl-wpp-faq .upl-faq-list { display:flex!important; flex-direction:column!important; gap:12px!important; }\n#upl-wpp-faq .upl-faq-item { background:#ffffff!important; border:1px solid #e5e7eb!important; border-radius:16px!important; overflow:hidden!important; transition:all 0.3s ease!important; }\n#upl-wpp-faq .upl-faq-item:hover { border-color:#3BB98B!important; box-shadow:0 4px 20px rgba(59,185,139,0.08)!important; }\n#upl-wpp-faq .upl-faq-item.active { border-color:#3BB98B!important; box-shadow:0 8px 30px rgba(59,185,139,0.12)!important; }\n#upl-wpp-faq .upl-faq-question { width:100%!important; display:flex!important; align-items:flex-start!important; justify-content:space-between!important; gap:20px!important; padding:24px 28px!important; background:transparent!important; border:none!important; cursor:pointer!important; text-align:left!important; }\n#upl-wpp-faq .upl-faq-question-content { display:flex!important; align-items:flex-start!important; gap:16px!important; flex:1!important; }\n#upl-wpp-faq .upl-faq-number { flex-shrink:0!important; padding:6px 12px!important; background:rgba(59,185,139,0.12)!important; color:#3BB98B!important; border-radius:20px!important; font-size:0.8rem!important; font-weight:600!important; }\n#upl-wpp-faq .upl-faq-item.active .upl-faq-number { background:rgba(59,185,139,0.2)!important; color:#2a9d6e!important; }\n#upl-wpp-faq .upl-faq-question-text { font-family:'Poppins',sans-serif!important; font-size:1.1rem!important; font-weight:600!important; color:#0f2736!important; line-height:1.4!important; padding-top:4px!important; }\n#upl-wpp-faq .upl-faq-icon { flex-shrink:0!important; width:36px!important; height:36px!important; background:#f4f5f7!important; border-radius:50%!important; display:flex!important; align-items:center!important; justify-content:center!important; transition:all 0.3s ease!important; margin-top:2px!important; }\n#upl-wpp-faq .upl-faq-icon svg { width:18px!important; height:18px!important; color:#64748b!important; transition:all 0.3s ease!important; }\n#upl-wpp-faq .upl-faq-item:hover .upl-faq-icon { background:rgba(59,185,139,0.1)!important; }\n#upl-wpp-faq .upl-faq-item:hover .upl-faq-icon svg { color:#3BB98B!important; }\n#upl-wpp-faq .upl-faq-item.active .upl-faq-icon { background:#3BB98B!important; transform:rotate(45deg)!important; }\n#upl-wpp-faq .upl-faq-item.active .upl-faq-icon svg { color:#ffffff!important; }\n#upl-wpp-faq .upl-faq-answer { max-height:0!important; overflow:hidden!important; transition:max-height 0.4s ease!important; }\n#upl-wpp-faq .upl-faq-item.active .upl-faq-answer { max-height:600px!important; }\n#upl-wpp-faq .upl-faq-answer-content { padding:0 28px 28px 76px!important; color:#475569!important; font-size:1rem!important; line-height:1.7!important; }\n#upl-wpp-faq .upl-faq-answer-content strong { color:#0f2736!important; font-weight:600!important; }\n#upl-wpp-faq .upl-faq-answer-content a { color:#3BB98B!important; text-decoration:underline!important; }\n#upl-wpp-faq .upl-faq-answer-content code { font-family:monospace!important; background:#f1f5f9!important; padding:2px 6px!important; border-radius:3px!important; font-size:0.85em!important; }\n#upl-wpp-faq .upl-faq-cta { margin-top:50px!important; display:flex!important; align-items:center!important; justify-content:space-between!important; gap:20px!important; padding:20px 28px!important; background:#ffffff!important; border:1px solid #e5e7eb!important; border-radius:12px!important; }\n#upl-wpp-faq .upl-faq-cta-text { color:#475569!important; font-size:1rem!important; }\n#upl-wpp-faq .upl-faq-cta-button { display:inline-flex!important; align-items:center!important; gap:10px!important; background:#DDDF4C!important; color:#0F2836!important; padding:13px 20px!important; border-radius:8px!important; text-decoration:none!important; font-weight:700!important; font-size:1rem!important; border:none!important; cursor:pointer!important; white-space:nowrap!important; }\n#upl-wpp-faq .upl-faq-cta-button:hover { transform:translateY(-2px)!important; }\n@media (max-width:768px) {\n  #upl-wpp-faq { padding:60px 16px!important; }\n  #upl-wpp-faq .upl-faq-answer-content { padding:0 20px 20px 20px!important; }\n  #upl-wpp-faq .upl-faq-question { padding:18px 20px!important; }\n  #upl-wpp-faq .upl-faq-cta { flex-direction:column!important; align-items:flex-start!important; }\n}\n<\/style>\n<section id=\"upl-wpp-faq\">\n  <div class=\"upl-faq-header\">\n    <h2 class=\"upl-faq-title\">WhatsApp API with PHP - FAQ<\/h2>\n    <div class=\"upl-faq-subtitle\">Straight answers on connecting, sending, Laravel, and the abandoned PHP SDK.<\/div>\n  <\/div>\n  <div class=\"upl-faq-list\">\n<div class=\"upl-faq-item active\">\n      <button class=\"upl-faq-question\" aria-expanded=\"true\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">01<\/span>\n          <span class=\"upl-faq-question-text\">How do you integrate the WhatsApp API in PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Create a Guzzle client pointed at the Unipile REST API, call <code>POST \/api\/v1\/accounts<\/code> with provider <code>WHATSAPP<\/code> to get a QR code or pairing code, have the user complete it on their phone, then use the same client for <code>GET<\/code>, <code>POST<\/code> and <code>PATCH<\/code> calls to send messages, list chats and manage groups. There is no PHP-specific endpoint, every call is a normal HTTP request with an <code>X-API-KEY<\/code> header. The <a href=\"#wpp-connect\">connect a WhatsApp account<\/a> section above walks through the exact code.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">02<\/span>\n          <span class=\"upl-faq-question-text\">Can you send a WhatsApp message programmatically with PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Yes. A single <code>POST<\/code> to <code>\/api\/v1\/chats\/{chat_id}\/messages<\/code> with a <code>text<\/code> field in a multipart body sends the message and returns a <code>message_id<\/code>, see the <a href=\"#wpp-send\">send section<\/a> above for the exact Guzzle call.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">03<\/span>\n          <span class=\"upl-faq-question-text\">Do you need a Meta Business verification to use WhatsApp with PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Only if you go through Meta's Cloud API directly or a Business Solution Provider built on top of it. Connecting a WhatsApp account through Unipile links the user's existing WhatsApp number by QR code or pairing code and does not require Meta Business verification at all.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">04<\/span>\n          <span class=\"upl-faq-question-text\">Is there an official Unipile PHP SDK?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>No actively maintained one. A community package, <code>unipile\/unipile-php-sdk<\/code>, is on Packagist but marked <strong>abandoned<\/strong>, with no commit since October 17, 2023 and 5 stars on GitHub. Every example in this guide calls the REST API directly through Guzzle instead, which is also what the abandoned SDK did internally.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">05<\/span>\n          <span class=\"upl-faq-question-text\">How do you receive WhatsApp messages in PHP without a public server?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>You cannot receive webhooks without a publicly reachable HTTPS URL, that is how HTTP callbacks work. During local development, tunnel a local port with a service like ngrok and point the webhook's <code>request_url<\/code> at the tunnel's HTTPS address. <a href=\"#wpp-retrieve\">Polling the messages endpoint<\/a> is the fallback when a public endpoint genuinely is not possible, at the cost of latency and extra requests.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">06<\/span>\n          <span class=\"upl-faq-question-text\">Does the WhatsApp API work with Laravel?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Yes, nothing about it is framework-specific. The <a href=\"#wpp-laravel\">Laravel section<\/a> above wraps the same Guzzle-equivalent calls in the <code>Http<\/code> facade, a queued job, and a webhook route and controller, which is the idiomatic way to structure it in a Laravel codebase.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">07<\/span>\n          <span class=\"upl-faq-question-text\">Can one PHP application manage WhatsApp accounts for multiple end users?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Yes, that is the normal SaaS shape. One Unipile API key covers the whole application, while every end user gets their own <code>account_id<\/code> after connecting their WhatsApp. Store that id next to your tenant record and pass it on outbound calls to prevent cross-tenant sends, see the <a href=\"#wpp-tenant\">multi-tenant section<\/a> above.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">08<\/span>\n          <span class=\"upl-faq-question-text\">How do you add someone to a WhatsApp group from PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div><code>PATCH \/api\/v1\/chats\/{chat_id}<\/code> with <code>{\"action\": \"addParticipant\", \"value\": \"&lt;phone&gt;@s.whatsapp.net\"}<\/code>. Meta's own Cloud API groups feature has no equivalent endpoint, only an invite link, which is one of the clearer differences between building directly on Meta and going through Unipile. Details in the <a href=\"#wpp-groups\">groups section<\/a> above.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">09<\/span>\n          <span class=\"upl-faq-question-text\">Why do emoji break in WhatsApp messages sent from PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Almost always because a string was truncated with <code>substr()<\/code> instead of <code>mb_substr()<\/code>. PHP's plain string functions count bytes, and an emoji is a multi-byte UTF-8 sequence, cut in the middle it turns into an invalid character or breaks the JSON payload entirely.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">10<\/span>\n          <span class=\"upl-faq-question-text\">Does Guzzle work, or do you need cURL directly?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Guzzle is enough, it is an HTTP client built on top of PHP's cURL extension, not a replacement for it. Every request in this guide uses Guzzle; a raw <code>curl_init()<\/code> call works identically if a project cannot add the dependency, the JSON and multipart bodies are the same either way.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">11<\/span>\n          <span class=\"upl-faq-question-text\">How much does sending a WhatsApp message from PHP cost?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>The same as sending it any other way. Meta bills per message since July 1, 2025, based on category and recipient country, not on the client library used to call the API. See the <a href=\"#wpp-cost\">cost section<\/a> above and the <a href=\"https:\/\/www.unipile.com\/whatsapp-business-api-pricing\/\">full pricing guide<\/a> for current rates.<\/div><\/div>\n      <\/div>\n    <\/div>\n<div class=\"upl-faq-item\">\n      <button class=\"upl-faq-question\" aria-expanded=\"false\">\n        <div class=\"upl-faq-question-content\">\n          <span class=\"upl-faq-number\">12<\/span>\n          <span class=\"upl-faq-question-text\">Is the 24-hour WhatsApp service window still relevant when using PHP?<\/span>\n        <\/div>\n        <div class=\"upl-faq-icon\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>\n        <\/div>\n      <\/button>\n      <div class=\"upl-faq-answer\">\n        <div class=\"upl-faq-answer-content\"><div>Yes, it is not going away, it just determines what is free rather than what is technically allowed. A reply inside the 24-hour window after a user's last message ships without being billed as a template message, PHP code that ignores the window simply pays for messages it did not need to.<\/div><\/div>\n      <\/div>\n    <\/div>\n<\/div>\n  <div class=\"upl-faq-cta\">\n    <pee class=\"upl-faq-cta-text\">Still have questions about building this in PHP? Our team is here to help.<\/pee>\n    <span class=\"upl-faq-cta-button\" onclick=\"if(window.$crisp){$crisp.push(['do','chat:open'])}\"><span>Talk to an expert<\/span><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg><\/span>\n  <\/div>\n<\/section>\n<script>\n(function(){\n  function initFaq(){\n    var faq=document.getElementById('upl-wpp-faq');\n    if(!faq)return;\n    faq.querySelectorAll('.upl-faq-question').forEach(function(btn){\n      btn.addEventListener('click',function(){\n        var item=btn.closest('.upl-faq-item');\n        var isActive=item.classList.contains('active');\n        faq.querySelectorAll('.upl-faq-item').forEach(function(i){i.classList.remove('active');i.querySelector('.upl-faq-question').setAttribute('aria-expanded','false');});\n        if(!isActive){item.classList.add('active');btn.setAttribute('aria-expanded','true');}\n      });\n    });\n    faq.addEventListener('click',function(e){\n      var el=e.target.closest('[data-upl-link]');\n      if(!el)return;\n      e.preventDefault();\n      window.open(el.getAttribute('data-upl-link'),el.getAttribute('data-upl-target')||'_blank');\n    });\n  }\n  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',initFaq);}else{initFaq();}\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=\"1\" _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.27.4\" background_color=\"transparent\" custom_padding=\"0px|0px|0px|0px|false|false\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.27.4\" global_colors_info=\"{}\"][et_pb_code _builder_version=\"4.27.4\" global_colors_info=\"{}\"]<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700;800&#038;display=swap\" rel=\"stylesheet\">\n<style>\n#upl-wpp-cta { background: transparent !important; }\n#upl-wpp-cta *, #upl-wpp-cta *::before, #upl-wpp-cta *::after {\n  margin: 0 !important;\n  padding: 0 !important;\n  box-sizing: border-box !important;\n  border: none !important;\n  outline: none !important;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;\n  line-height: normal !important;\n  letter-spacing: normal !important;\n  text-transform: none !important;\n  text-decoration: none !important;\n  list-style: none !important;\n  background: transparent !important;\n  float: none !important;\n}\n#upl-wpp-cta br { display: none !important; }\n#upl-wpp-cta p { display: contents !important; }\n#upl-wpp-cta { padding: 20px 20px 70px !important; overflow-x: hidden !important; max-width: 100vw !important; }\n#upl-wpp-cta .wpe-panel { max-width: 1100px !important; margin: 0 auto !important; background: #0f2736 !important; border-radius: 24px !important; padding: 56px 60px !important; text-align: center !important; }\n#upl-wpp-cta .wpe-badge { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: rgba(59,185,139,0.16) !important; color: #6fe3b8 !important; padding: 6px 14px !important; border-radius: 20px !important; font-size: 12px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; margin-bottom: 22px !important; }\n#upl-wpp-cta .wpe-badge-dot { width: 7px !important; height: 7px !important; background: #3BB98B !important; border-radius: 50% !important; flex-shrink: 0 !important; }\n#upl-wpp-cta h2 { font-family: 'Poppins', sans-serif !important; font-size: 35px !important; font-weight: 700 !important; color: #ffffff !important; line-height: 1.25 !important; margin: 0 auto 18px !important; }\n#upl-wpp-cta .wpe-desc { font-size: 16.5px !important; line-height: 1.75 !important; color: rgba(255,255,255,0.78) !important; margin: 0 auto 34px !important; }\n#upl-wpp-cta .wpe-desc code { font-family: 'Courier New', monospace !important; background: rgba(255,255,255,0.1) !important; padding: 2px 6px !important; border-radius: 4px !important; font-size: 0.9em !important; color: #ffffff !important; }\n#upl-wpp-cta .wpe-actions { display: flex !important; align-items: center !important; justify-content: center !important; gap: 14px !important; flex-wrap: wrap !important; margin-bottom: 26px !important; }\n#upl-wpp-cta .wpe-cta-primary { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: #DDDF4C !important; color: #0f2736 !important; padding: 15px 30px !important; border-radius: 8px !important; font-size: 0.98rem !important; font-weight: 600 !important; border: 2px solid #DDDF4C !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-cta .wpe-cta-primary:hover { transform: translateY(-5px) !important; }\n#upl-wpp-cta .wpe-cta-primary svg { width: 16px !important; height: 16px !important; stroke: currentColor !important; fill: none !important; stroke-width: 2.5 !important; stroke-linecap: round !important; stroke-linejoin: round !important; }\n#upl-wpp-cta .wpe-cta-secondary { display: inline-flex !important; align-items: center !important; gap: 8px !important; background: transparent !important; color: #ffffff !important; padding: 13px 28px !important; border-radius: 8px !important; font-size: 0.98rem !important; font-weight: 600 !important; border: 2px solid rgba(255,255,255,0.35) !important; transition: all 0.3s ease !important; cursor: pointer !important; white-space: nowrap !important; }\n#upl-wpp-cta .wpe-cta-secondary:hover { background: rgba(255,255,255,0.1) !important; border-color: rgba(255,255,255,0.6) !important; }\n#upl-wpp-cta .wpe-note { font-size: 0.88rem !important; color: rgba(255,255,255,0.55) !important; }\n#upl-wpp-cta .wpe-note a { color: #6fe3b8 !important; text-decoration: underline !important; }\n@media (max-width: 900px) {\n  #upl-wpp-cta .wpe-panel { padding: 46px 32px !important; border-radius: 20px !important; }\n  #upl-wpp-cta h2 { font-size: 28px !important; }\n}\n@media (max-width: 600px) {\n  #upl-wpp-cta { padding: 10px 16px 50px !important; }\n  #upl-wpp-cta .wpe-panel { padding: 38px 22px !important; }\n  #upl-wpp-cta h2 { font-size: 25px !important; }\n  #upl-wpp-cta .wpe-desc { font-size: 15px !important; }\n  #upl-wpp-cta .wpe-actions { flex-direction: column !important; width: 100% !important; }\n  #upl-wpp-cta .wpe-cta-primary, #upl-wpp-cta .wpe-cta-secondary { width: 100% !important; justify-content: center !important; }\n}\n<\/style>\n<div id=\"upl-wpp-cta\">\n  <div class=\"wpe-panel\">\n    <div class=\"wpe-badge\"><span class=\"wpe-badge-dot\"><\/span><span>WhatsApp API PHP Guide<\/span><\/div>\n    <h2>Ready to build the WhatsApp API into your PHP application?<\/h2>\n    <div class=\"wpe-desc\">Every endpoint in this guide, connect, send, receive, groups, runs on the same Unipile account you can create right now. No Meta Business verification, no abandoned SDK, just <code>Guzzle<\/code> and a REST API your PHP application already knows how to call.<\/div>\n    <div class=\"wpe-actions\">\n      <a class=\"wpe-cta-primary\" href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\" data-upl-target=\"_blank\">\n        <span>Build your WhatsApp integration<\/span>\n        <svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg>\n      <\/a>\n      <a class=\"wpe-cta-secondary\" href=\"https:\/\/developer.unipile.com\/docs\" target=\"_blank\" rel=\"noopener\" data-upl-link=\"https:\/\/developer.unipile.com\/docs\" data-upl-target=\"_blank\">\n        <span>Read the API docs<\/span>\n      <\/a>\n    <\/div>\n    <div class=\"wpe-note\">Automating instead of integrating into an existing app? Read <a href=\"https:\/\/www.unipile.com\/whatsapp-api-python\/\">the same integration in Python<\/a>.<\/div>\n  <\/div>\n<\/div>\n<script>\n(function(){\n  function init(){\n    var wrapper = document.getElementById('upl-wpp-cta');\n    if (!wrapper) return;\n    wrapper.addEventListener('click', function(e){\n      var el = e.target.closest('[data-upl-link]');\n      if (!el) return;\n      e.preventDefault();\n      e.stopPropagation();\n      var url = el.getAttribute('data-upl-link');\n      var target = el.getAttribute('data-upl-target');\n      if (target === '_blank') { window.open(url, '_blank'); } else { window.location.href = url; }\n    }, true);\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section]\n","protected":false},"excerpt":{"rendered":"<p>WhatsApp API PHP Guide WhatsApp API with PHP: The Complete Integration Guide Guzzle and cURL calls to connect a WhatsApp account, send and receive messages, manage groups and run the whole thing inside a Laravel application, without registering a Meta Business app. This is the WhatsApp API in PHP end to end: connection, webhooks, multi-tenant [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":279776,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"","inline_featured_image":false,"footnotes":""},"categories":[69],"tags":[],"post_folder":[],"class_list":["post-279754","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-api-guidelines"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>WhatsApp API with PHP: The Complete Integration Guide - Unipile<\/title>\n<meta name=\"description\" content=\"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.unipile.com\/fr\/whatsapp-api-php\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WhatsApp API with PHP: The Complete Integration Guide - Unipile\" \/>\n<meta property=\"og:description\" content=\"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.unipile.com\/fr\/whatsapp-api-php\/\" \/>\n<meta property=\"og:site_name\" content=\"Unipile\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/unipilefr\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-13T13:44:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-13T13:48:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Damien Girardeau\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@UnipileAPI\" \/>\n<meta name=\"twitter:site\" content=\"@UnipileAPI\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Damien Girardeau\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/\"},\"author\":{\"name\":\"Damien Girardeau\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/person\\\/a2ac44e22bdc27d497ce8b58716a673e\"},\"headline\":\"WhatsApp API with PHP: The Complete Integration Guide\",\"datePublished\":\"2026-08-13T13:44:48+00:00\",\"dateModified\":\"2026-08-13T13:48:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/\"},\"wordCount\":4215,\"publisher\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/whatsapp-api-php-featured.png\",\"articleSection\":[\"API Guidelines\"],\"inLanguage\":\"fr-FR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/\",\"name\":\"WhatsApp API with PHP: The Complete Integration Guide - Unipile\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/whatsapp-api-php-featured.png\",\"datePublished\":\"2026-08-13T13:44:48+00:00\",\"dateModified\":\"2026-08-13T13:48:44+00:00\",\"description\":\"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/whatsapp-api-php-featured.png\",\"contentUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/whatsapp-api-php-featured.png\",\"width\":2400,\"height\":1600,\"caption\":\"Calling the WhatsApp API from PHP with Guzzle, straight against the REST API\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/whatsapp-api-php\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.unipile.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"WhatsApp API with PHP: The Complete Integration Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#website\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/\",\"name\":\"Unipile\",\"description\":\"Integrate Messaging &amp; Email, Connect with Ease via API\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.unipile.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\",\"name\":\"Unipile\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-unipile.png\",\"contentUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-unipile.png\",\"width\":200,\"height\":49,\"caption\":\"Unipile\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/unipilefr\",\"https:\\\/\\\/x.com\\\/UnipileAPI\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/unipile\\\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/person\\\/a2ac44e22bdc27d497ce8b58716a673e\",\"name\":\"Damien Girardeau\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"caption\":\"Damien Girardeau\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WhatsApp API with PHP: The Complete Integration Guide - Unipile","description":"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.unipile.com\/fr\/whatsapp-api-php\/","og_locale":"fr_FR","og_type":"article","og_title":"WhatsApp API with PHP: The Complete Integration Guide - Unipile","og_description":"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.","og_url":"https:\/\/www.unipile.com\/fr\/whatsapp-api-php\/","og_site_name":"Unipile","article_publisher":"https:\/\/www.facebook.com\/unipilefr","article_published_time":"2026-08-13T13:44:48+00:00","article_modified_time":"2026-08-13T13:48:44+00:00","og_image":[{"width":2400,"height":1600,"url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png","type":"image\/png"}],"author":"Damien Girardeau","twitter_card":"summary_large_image","twitter_creator":"@UnipileAPI","twitter_site":"@UnipileAPI","twitter_misc":{"\u00c9crit par":"Damien Girardeau","Dur\u00e9e de lecture estim\u00e9e":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#article","isPartOf":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/"},"author":{"name":"Damien Girardeau","@id":"https:\/\/www.unipile.com\/#\/schema\/person\/a2ac44e22bdc27d497ce8b58716a673e"},"headline":"WhatsApp API with PHP: The Complete Integration Guide","datePublished":"2026-08-13T13:44:48+00:00","dateModified":"2026-08-13T13:48:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/"},"wordCount":4215,"publisher":{"@id":"https:\/\/www.unipile.com\/#organization"},"image":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png","articleSection":["API Guidelines"],"inLanguage":"fr-FR"},{"@type":"WebPage","@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/","url":"https:\/\/www.unipile.com\/whatsapp-api-php\/","name":"WhatsApp API with PHP: The Complete Integration Guide - Unipile","isPartOf":{"@id":"https:\/\/www.unipile.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#primaryimage"},"image":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png","datePublished":"2026-08-13T13:44:48+00:00","dateModified":"2026-08-13T13:48:44+00:00","description":"Integrate WhatsApp in PHP with Guzzle or cURL: connect an account, send messages, verify webhooks, ship it in Laravel. Full code, no Meta verification.","breadcrumb":{"@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.unipile.com\/whatsapp-api-php\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#primaryimage","url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png","contentUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/08\/whatsapp-api-php-featured.png","width":2400,"height":1600,"caption":"Calling the WhatsApp API from PHP with Guzzle, straight against the REST API"},{"@type":"BreadcrumbList","@id":"https:\/\/www.unipile.com\/whatsapp-api-php\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.unipile.com\/"},{"@type":"ListItem","position":2,"name":"WhatsApp API with PHP: The Complete Integration Guide"}]},{"@type":"WebSite","@id":"https:\/\/www.unipile.com\/#website","url":"https:\/\/www.unipile.com\/","name":"Unipile","description":"Int\u00e9grer la messagerie et l'e-mail, se connecter facilement via l'API","publisher":{"@id":"https:\/\/www.unipile.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.unipile.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/www.unipile.com\/#organization","name":"Unipile","url":"https:\/\/www.unipile.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.unipile.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2021\/05\/logo-unipile.png","contentUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2021\/05\/logo-unipile.png","width":200,"height":49,"caption":"Unipile"},"image":{"@id":"https:\/\/www.unipile.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/unipilefr","https:\/\/x.com\/UnipileAPI","https:\/\/www.linkedin.com\/company\/unipile\/"]},{"@type":"Person","@id":"https:\/\/www.unipile.com\/#\/schema\/person\/a2ac44e22bdc27d497ce8b58716a673e","name":"Damien Girardeau","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","caption":"Damien Girardeau"}}]}},"_links":{"self":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/279754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/comments?post=279754"}],"version-history":[{"count":9,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/279754\/revisions"}],"predecessor-version":[{"id":279775,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/279754\/revisions\/279775"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/media\/279776"}],"wp:attachment":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/media?parent=279754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/categories?post=279754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/tags?post=279754"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/post_folder?post=279754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}