Store Platforms

Wix API Integration: Auth, Webhooks and the Catalog V3 Trap

Wix API integration explained: OAuth vs API keys, access tokens, the Catalog V1 vs V3 trap and webhooks that retry 12 times, with working code.

Photo de profil de Long Nguyen

Long Nguyen

Développeur fullstack · Ingénieur IA · Chercheur

• • 5 min de lecture •

What Wix API integration covers

A Wix API integration is code that reads or writes Wix data (products, orders, contacts, bookings) through Wix's REST API or JavaScript SDK, or reacts to Wix events through webhooks. It can run on the Wix site itself, on your own server, or inside an app installed on other people's sites.

Where the code runs decides how it authenticates, and that choice shapes everything else. Wix's own documentation splits it into five paths:

Path Where your code runs Authentication
Extending a Wix site On the Wix site Host auth, applied automatically
Wix-managed app (CLI or Blocks) Wix-hosted Built in; Wix issues app-instance tokens for backend code
Self-managed app Your server, installed on merchants' sites OAuth
Headless project Any stack you choose OAuth for visitors and members; client credentials or an API key for admin work
External automation Your server, script or CI job API key

Most "connect my Wix store to another system" projects land in the last two rows. Decide which one you are in before writing any code, because the credentials, token lifetimes and permission model all differ.

OAuth or API key: which Wix authentication to use

Wix supports OAuth and API keys for code that runs outside the Wix dashboard, editor or site. They are not interchangeable.

  OAuth API key
Best for Apps installed on many sites; visitor, member and app identities Server-to-server automation, external integrations, admin work across sites you manage
Lifetime Access token valid for 4 hours Valid until revoked or rotated in the Wix dashboard
Renewal Visitor and member tokens: refresh token, 365 days by default, rotated on each use. App tokens: no refresh token, mint a new one Not applicable
Issued by Your app or headless project's OAuth client An account owner or co-owner, in the dashboard
Permission model Scopes granted to the app Scopes plus site access (all sites in the account, or chosen sites only)
Third-party Wix apps Required Not available

The rule of thumb for real projects: if the integration will be installed by more than one merchant or listed in the App Market, build an app and use OAuth. If it connects one business's Wix site to that same business's ERP, warehouse or marketplace tooling, a scoped API key is the shorter path, with a headless project's client credentials as the alternative when you only need admin access to that project's own site.

Treat an API key like an account password. Restrict it to the narrowest set of sites and scopes the integration needs, keep it in a secrets manager, and remember that site-level calls only work with keys generated from the account that owns the site. If you are doing this for a client, they will need to create the key, because only account owners and co-owners can.

How to get a Wix access token with client credentials

For admin operations in a headless project, the client credentials grant exchanges your OAuth client ID and secret for a short-lived token. Run it only in backend code. The secret is shown once when you generate it in Headless Settings, so store it immediately.

The token endpoint is https://www.wixapis.com/oauth2/token, and the response includes an expires_in of 14400 seconds. Do not request a new token on every call. Cache it and renew shortly before expiry:

let cached = { token: null, expiresAt: 0 };

async function getWixToken() {
  const now = Date.now();
  if (cached.token && now < cached.expiresAt - 5 * 60 * 1000) {
    return cached.token;
  }
  const res = await fetch('https://www.wixapis.com/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'client_credentials',
      client_id: process.env.WIX_CLIENT_ID,
      client_secret: process.env.WIX_CLIENT_SECRET
    })
  });
  if (!res.ok) throw new Error('Wix token request failed: ' + res.status);
  const data = await res.json();
  cached = { token: data.access_token, expiresAt: now + data.expires_in * 1000 };
  return cached.token;
}

async function wixPost(path, body) {
  const token = await getWixToken();
  const res = await fetch('https://www.wixapis.com' + path, {
    method: 'POST',
    headers: { 'Authorization': token, 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  return res.json();
}

Note that the token goes into the Authorization header exactly as returned, with no extra prefix. An API key is sent in the same header. If a call returns 401, the token has most likely expired, so a renew-and-retry-once wrapper around wixPost is worth adding.

Wix Stores Catalog V1 vs V3: the trap in most integrations

This is where store integrations quietly break. Wix Stores has two product catalog APIs, and a given site is on one or the other. According to Wix's Catalog Versioning documentation, the two versions are not backwards compatible, all sites will eventually move to V3, and you should call the GetCatalogVersion endpoint at the beginning of each flow to know which API to use. Each version also fires its own webhooks, so an integration that must serve every site subscribes to both V1 and V3 events.

Wix's migration guide also states that there is no automatic migration path and that an app must support both versions to be installable by new and existing sites. The differences that matter in practice:

Area Catalog V1 Catalog V3
Products without options Plain product One default variant with an empty choices array; every purchasable entity is a variant
Variants in query results Handled by V1 calls Query and Search endpoints do not return variants; use the Read-Only Variants API
Stock stock.quantity on the product Inventory Items API, searched by productId and/or variantId
Discounted price price and discountedPrice With a discount: V1 price becomes compareAtPrice, V1 discountedPrice becomes actualPrice. Without: price becomes actualPrice
Options Options with managedVariants true or false Customizations API: options (create variants) and modifiers (do not)
Custom text fields customTextFields Modifiers of type FREE_TEXT
Paging numericId used for cursor paging Cursor paging built into Query and Search
Events V1 webhooks V3 webhooks with a changed payload structure

The expensive mistake is writing against V3 because it is newer, then discovering a merchant's store is still on V1, or the reverse. Put an adapter between your business logic and Wix so that the version check happens once:

// One interface, two implementations. Business logic never sees the version.
const catalog = (await isCatalogV3(siteAuth))
  ? new CatalogV3(siteAuth)
  : new CatalogV1(siteAuth);

const products = await catalog.listProducts();
const stock = await catalog.getStock(productId);

The V3 stock and variant split is the part that costs the most rework: what used to be one product read becomes a product query, a variants query and an inventory search. If you would rather not maintain two code paths yourself, this is the kind of work our Wix and ecommerce platform integration service covers.

How to handle Wix webhooks without losing events

Wix sends webhook data as a signed JSON Web Token in the request body, and you verify it with the public key from the Webhooks page of your app dashboard. The behavior below comes from Wix's webhooks documentation:

  • Your endpoint must return HTTP 200 within 1250 ms, or Wix treats the delivery as failed.
  • On failure, up to 12 additional attempts follow on a retry schedule.
  • A resent webhook can arrive after a newer one that succeeded first time, so events can be delayed and out of order.
  • Webhooks do not always carry the full entity, and Wix recommends designing for duplicate events.
  • Sites on older major versions of your app do not receive newly added webhooks.

A 1250 ms window leaves no room for database writes or follow-up API calls. The handler should verify the signature, hand the event to a queue, and return 200. Nothing else:

import express from 'express';
import jwt from 'jsonwebtoken';

const app = express();

app.post('/webhooks/wix', express.text({ type: '*/*' }), function (req, res) {
  let event;
  try {
    event = jwt.verify(req.body, process.env.WIX_APP_PUBLIC_KEY, {
      algorithms: ['RS256']
    });
  } catch (err) {
    return res.sendStatus(401);
  }
  queue.add(event); // your own job queue: parse and process later
  res.sendStatus(200);
});

If you build with the Wix CLI, event extensions handle the payload for you, so this handler is only needed for self-hosted apps. The Logs tab on the Webhooks page of the app dashboard shows every delivery and is the first place to look when events seem to be missing.

A sync pattern that survives retries and outages

Because deliveries can repeat, arrive late or arrive out of order, a handler that says "stock changed, subtract 1" will drift. Wix's payload is a signal that something changed, not a ledger. This pattern holds up:

  1. Acknowledge fast. Verify, enqueue a small job (event type and entity ID), return 200.
  2. Re-read, do not trust the payload. The worker fetches the current entity from the Wix API, so the state it writes is always the latest one.
  3. Upsert on the Wix entity ID. Running the same job twice must produce the same result.
  4. Reconcile on a schedule. Wix itself recommends periodic API requests to confirm webhooks are accurate. A nightly query of recently changed products or orders catches anything a webhook missed.
  5. Cap concurrency and back off on HTTP 429. Bulk imports are where integrations trip over request limits.

Steps 2 and 4 are the difference between an integration that works in a demo and one that stays correct for months.

Wix API errors and what causes them

Symptom Likely cause Fix
401 on any REST call OAuth access token expired (4-hour lifetime) Mint or refresh a token and retry once
401 on a Stores call: invalid authorization token, or Wix Stores not installed Token does not belong to that site, or the site has no Wix Stores Confirm the site has Stores installed and the token was issued for it
403 with an API key Key lacks the scope for that operation, or the target site is outside the key's site access Adjust scopes and site access in the API Keys Manager
Site-level call fails with a valid key Key was generated from a different account than the one that owns the site Use a key from the owning account
Products have no variants after switching to V3 V3 Query and Search do not return variants Use the Read-Only Variants API
Integration works on one store, fails on another The two stores are on different catalog versions Call GetCatalogVersion first and branch
Some sites never get a new webhook Site is on an older major version of your app Ask merchants to update; check the Logs tab
Same event processed twice Retry after a missed 200 or a timeout over 1250 ms Deduplicate and make handlers idempotent

Build it in-house or hire it out

A one-directional, read-only export from a single Wix store, owned by a team with a backend developer, is a reasonable in-house project. The picture changes when any of these is true:

  • The sync is two-way (orders in, stock and tracking out) across marketplaces, an ERP or a warehouse system.
  • More than one Wix store is involved, so you will meet both catalog versions.
  • Nobody on your side wants to own webhook reliability, token handling and reconciliation long term.

Before you brief anyone, write down five answers: which direction data flows, which entities are involved (products, orders, customers), which catalog version each store is on, who owns the Wix account that can create an API key, and what should happen when a sync fails at 3 a.m. Those five answers are most of the scope.

If you want a second opinion or a build quote, request a free quote for your Wix integration with your store, the system you need to connect and the data involved. Pricing is set to scope.

FAQ

Questions fréquentes

Does Wix have a public API?

Yes. Wix offers a REST API for HTTP-based access to its business solutions and site data, such as Wix Stores products and orders, plus a JavaScript SDK and webhooks for events.

Do I need to build a Wix app to integrate my own store with another system?

Not necessarily. For server-to-server automation on sites you manage, an API key is designed for that use, and a headless project can use client credentials for admin calls. An app with OAuth is required when you distribute through the Wix App Market or install on other merchants' sites.

How long does a Wix access token last?

OAuth access tokens are valid for 4 hours. Visitor and member tokens come with a refresh token valid for 365 days by default, while app tokens from client credentials have no refresh token and must be minted again. API keys stay valid until you revoke or rotate them.

Can I use a Wix API key inside a third-party Wix app?

No. Wix API keys are not available for third-party apps. Apps must authenticate with OAuth.

What is the difference between Wix Stores Catalog V1 and V3?

They are two separate, non-backwards-compatible product catalog APIs. In V3 every product has at least one variant, stock lives in the Inventory Items API, options and modifiers are managed through the Customizations API, and V3 query endpoints do not return variants. Call GetCatalogVersion to see which one a site uses.

How fast must my endpoint answer a Wix webhook?

Within 1250 ms with an HTTP 200. If it does not, Wix retries up to 12 more times, which means duplicates and out-of-order events are normal and your handler should be idempotent.

Restez informé avec Netalith

Recevez des ressources de développement, des mises à jour produit et des offres spéciales directement dans votre boîte mail.