Headless Store API Integration: REST APIs, Webhooks, and How to Connect Third-Party Systems
1. WordPress REST API: understand the built-in capabilities first
WordPress has had a native REST API since version 4.7, no plugin required. The endpoint format is https://your-domain/wp-json/wp/v2/posts. Visit it in a browser and you’ll see your posts as JSON. This API is public by default, so anyone can read your posts, pages, and media library. That’s both a good thing (easy to integrate) and a risk (exposes internal data).
Write operations (creating posts, updating orders, adding users) require authentication. WordPress supports two methods: Application Passwords (simple, generated on the user profile page, good for your own server calls) and OAuth 2.0 (complex, good for authorizing third-party apps). Application Passwords are enough for connecting your headless store to your own CRM. Don’t hardcode the admin account password in your code just to keep things simple.
Decision framework: do you need to read data from WordPress or write data to it? Read-only (pulling post lists, order records): use GET requests with an Application Password. Write (creating orders, updating users, sending Webhooks): you need POST/PUT requests, and permissions should be minimized. For example, grant only “edit orders” permission, not “manage all settings.” For how to set up your tech stack, see crater Tech Stack.
| Endpoint | Method | Purpose | Certification requirements |
|---|---|---|---|
| /wp-json/wp/v2/posts | GET | Read post list | Public (published) |
| /wp-json/wp/v2/posts | POST | Create post | Application Password |
| /wp-json/wc/v3/orders | GET | Read WooCommerce orders | Consumer Key |
| /wp-json/wc/v3/orders | POST | Create order | Consumer Key |
| /wp-json/wp/v2/users | GET | Read user list | Admin password |
| /wp-json/wp/v2/media | POST | Upload image | Edit the above passwords |
2. Webhooks: event-driven real-time notifications
Webhooks and REST APIs work in opposite directions. With REST, you go to the other server and pull the data. With a webhook, the other server pushes data to you the moment an event happens. For example, when WooCommerce gets a new order, it sends a POST request to the URL you set in your webhook config, with the order details as JSON in the body. You don’t have to poll “any new orders?” every minute — the order comes to you automatically.
WooCommerce supports webhooks out of the box. Add one under WooCommerce → Settings → Advanced → Webhooks. You’ll need to fill in: the trigger event (order created, order updated, order cancelled), the delivery URL (an endpoint on your own server, e.g. https://yourdomain.com/wp-json/custom/v1/new-order), and the signature method (HMAC-SHA256, using a secret to verify the request really came from WooCommerce and isn’t forged).
A counterintuitive take:When a webhook delivery fails, you probably won’t know. If your server returns a 500 when WooCommerce pushes a webhook, it retries a few times (5 by default, with increasing intervals). But if all 5 fail, it gives up — you never got the data, and you got no alert either. That’s why you can’t rely on webhooks alone for critical data: you need scheduled pulls as a fallback. For CRM integration, see CRM Integration for Your Own Store.
| Event | WooCommerce Hook | Where it goes | Priority |
|---|---|---|---|
| New order created | woocommerce_order_created | CRM + Slack notification | Highest |
| Order status changed | woocommerce_order_status_changed | Customer email + CRM update | High |
| Payment complete | woocommerce_payment_complete | Membership upgrade | High |
| Refund issued | woocommerce_order_refunded | CRM tag + finance notification | Medium |
| New user registered | user_register | Email marketing list | Medium |
| Product published/unpublished | woocommerce_product_set_visibility | Inventory system sync | Low |
3. Scheduled REST pulls: reconciliation as a fallback
Webhooks give you real-time notification in seconds, but you still need a scheduled pull as a reconciliation layer. It’s simple: write a WP-Cron script that runs hourly, calls the WooCommerce REST API to pull orders created or updated in the past hour, and compares them against the orders already in your database. If a webhook missed an order (say your server returned a 502 right when it was pushed), the scheduled pull fills in the gap.
Your scheduled pull query needs a timestamp. For example, GET /wp-json/wc/v3/orders?after=2026-09-21T10:00:00&per_page=100 returns all orders after 10:00, 100 per page. If you get 100 back, there may be more, so keep paging. Once you’re done, dedupe by order ID: skip the ones already in your database, insert the ones that aren’t. That’s the simplest reconciliation logic there is.
Example: On a Wednesday at 3:00 PM, the server’s SSL certificate expires and returns a 525 error for 40 minutes. During that window, the webhooks for 3 new orders all fail. With webhooks alone, those 3 orders are lost. But with hourly polling set up, the 4:00 PM run picks up the 3 missed orders and customers get their confirmation emails. For how to set up monitoring, see Site monitoring and alerts.
| Sync method | Frequency | Latency | On failure |
|---|---|---|---|
| Webhook push | Event-triggered | Seconds | Sender gives up after 5 retries |
| Hourly polling | Every hour on the hour | Minutes | Automatically retries on the next run if it fails |
| Daily full reconciliation | Every day at 3:00 AM | Days | Generates a discrepancy report for manual review |
| Real-time WebSocket | Real-time | Millisecond-level | Must reconnect if the connection drops |
4. Authentication and security: keep keys on the backend, verify request signatures
The most common security mistake in API integrations is putting your API key in front-end JavaScript. Anyone can open their browser, hit F12 → Network, see your key, and use it to call your API however they like. The right approach: the front end only calls your own server’s endpoints, and the server adds the API key on the backend before forwarding the request to the third party. That backend proxy can be a custom WordPress REST endpoint, or a simple Node.js/Python service.
You must verify signatures when receiving webhooks. When WooCommerce sends a webhook, it adds an X-WC-Webhook-Signature to the HTTP header, which is an HMAC-SHA256 signature of the body using your webhook secret. At your receiving endpoint, compute the same signature and compare it against the one in the header. Only process the request if they match. If they don’t match, someone forged the request, so return 403. The consequence of not verifying signatures: anyone can POST fake orders to your endpoint, and your CRM fills up with junk leads.
Example: You’re receiving HubSpot webhooks, and someone learns your receiving URL and crafts a fake “new lead” POST request. If you don’t verify signatures, that fake lead lands in HubSpot, and sales chases it for half a day before realizing it’s fake. With HMAC verification in place, HubSpot’s requests carry the correct signature, the fake request doesn’t, and it gets blocked with a 403. For CRM integration details, see CRM Integration for Your Own Store.
| Security item | What not to do | The right way |
|---|---|---|
| API key location | Written into front-end JS | Stored in server environment variables |
| Request proxying | Front end calls third-party APIs directly | Front end calls your own server, backend forwards |
| Webhook signature verification | No verification, process on receipt | HMAC-SHA256 compared against the header |
| HTTPS | Receiving webhooks over HTTP | HTTPS required, TLS 1.2 or higher |
| IP allowlist | No restriction on source IPs | Allowlist based on the third party’s official IP ranges |
| Error Log | Failures aren’t logged | All non-2xx responses are logged |
5. Common third-party integration checklist
There are five common types of third-party integrations for a DTC site: CRM (HubSpot, Salesforce, Zoho), email marketing (Mailchimp, ConvertKit, Klaviyo), payment gateways (Stripe, PayPal), analytics (Google Analytics 4, Hotjar), and customer support (Intercom, Zendesk). Each one connects differently, but they all follow the same rule: use a Webhook whenever you can (real-time), and add a scheduled pull for critical data (as a fallback).
Don’t start by writing your own integration code. First check whether the WordPress plugin directory already has a plugin for it: HubSpot has an official plugin, Mailchimp has an official plugin, and Stripe has an official WooCommerce extension. Off-the-shelf plugins cover 80% of use cases; handle the remaining 20% (custom field mapping, for example) with Webhooks or custom code. Writing your own integration between two systems usually takes over 20 hours to debug, while installing an existing plugin takes about an hour. For how to choose a CRM plugin, see Website leads to CRM.
| System type | Recommended Plan | Integration method | Estimated hours |
|---|---|---|---|
| CRM (HubSpot) | Official plugin + Webhook | Plugin syncs automatically | 2 to 4 hours |
| Email marketing (Mailchimp) | Official plugin | Adds users to a list on signup | 1 to 2 hours |
| Payments (Stripe) | Official WooCommerce extension | Webhook syncs order status | 1 to 2 hours |
| Analytics (GA4) | Site Kit by Google plugin | Automatic front-end tracking | 30 minutes |
| Support (Intercom) | Official chat plugin | Front-end code snippet | 30 minutes |
| Custom ERP | Write your own REST integration | Scheduled pull + Webhook | 20+ hours |
FAQ
What’s the difference between REST API and Webhook, and which is better?
Does the WordPress REST API require a plugin?
Where should I put an API Key, and can I use it on the front end?
How does a webhook receiver verify that a request is genuine?
What if a webhook delivery fails?
For connecting to third-party systems, should I use an off-the-shelf plugin or write my own?
Final thoughts
API integration is not about being as complex as possible, but as reliable as possible. There is only one goal: no data lost, no wrong status, and problems you can trace. Webhooks are fast but unreliable; REST is slow but controllable. Stack the two together and you have a production-grade solution. Use either one on its own and you will lose data at some point.
Three steps to put it in place: use webhooks for real-time notifications on critical integrations, with HMAC signature verification on the receiving end; add an hourly scheduled REST pull for reconciliation, so anything the webhook missed is recovered automatically; keep all API keys in backend environment variables, and have the frontend call only your own server’s proxy endpoints.
One line worth remembering: webhooks are “instant alerts,” REST is “scheduled reconciliation” — relying on alerts alone without reconciling is like hearing the doorbell but never checking the parcel locker.
