Storefront AJAX API

These endpoints power theme JavaScript on the storefront. They use the customer session and CSRF — they are not the partner Web API under /api/v1/.

Do not confuse auth models: Web API keys (X-API-Key) do not work here. Never put SHOP_TOKEN, admin tokens, or cron tokens into storefront AJAX as CSRF. Use the session CSRF token from header.tpl (csrfToken in JS) or a meta / form field named token / header X-CSRF-Token.

Common endpoints

EndpointMethodActions / notes
/api/auth.php POST login, register, logout, me
/api/cart.php POST add, update, remove, clear, get
/api/coupon.php POST apply, remove, set_cargo, set_payment, summary
/api/account.php POST Profile, password, addresses, notifications
/api/favorite.php POST toggle, remove
/api/product.php?id= GET Quick view JSON
/api/search-suggest.php?q= GET Autocomplete suggestions
/api/module.php?m={module}&action={action} POST / GET Module APIs (still CSRF-protected unless exempt)

CSRF checklist

  • Send token in the body, or X-CSRF-Token header
  • Compare on the server with hash_equals($_SESSION['csrf_token'], $token)
  • Login / register may also run captcha hooks (form.captcha.validate)
Modules & themes: Build storefront features with display hooks and module APIs — see Create New Module, Hook List, and Create Template.
PHP
// Cart AJAX — CSRF from global csrfToken (header.tpl) or meta[name="csrf-token"]
(function () {
  function getCsrfToken() {
    if (typeof window.csrfToken === 'string' && window.csrfToken !== '') {
      return window.csrfToken;
    }
    var meta = document.querySelector('meta[name="csrf-token"]');
    return meta ? meta.getAttribute('content') : '';
  }

  function cartRequest(action, body) {
    var data = Object.assign({ action: action, token: getCsrfToken() }, body || {});
    return fetch('/api/cart.php', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-CSRF-Token': getCsrfToken(),
        'Accept': 'application/json'
      },
      credentials: 'same-origin',
      body: new URLSearchParams(data).toString()
    }).then(function (res) {
      return res.json();
    });
  }

  // Add product id 12 (optional variation)
  cartRequest('add', {
    id_product: '12',
    id_variation: '0',
    qty: '1'
  }).then(function (json) {
    console.log(json);
  });
})();
Login (auth.php) — with CSRF
// Login via storefront auth API (session + CSRF, not X-API-Key)
(function () {
  function getCsrfToken() {
    if (typeof window.csrfToken === 'string' && window.csrfToken !== '') {
      return window.csrfToken;
    }
    var meta = document.querySelector('meta[name="csrf-token"]');
    return meta ? meta.getAttribute('content') : '';
  }

  fetch('/api/auth.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      'X-CSRF-Token': getCsrfToken(),
      'Accept': 'application/json'
    },
    credentials: 'same-origin',
    body: new URLSearchParams({
      action: 'login',
      token: getCsrfToken(),
      login: 'customer@example.com',
      password: 'secret',
      remember: '1'
    }).toString()
  })
    .then(function (res) { return res.json(); })
    .then(function (json) {
      console.log(json);
      if (json.success && json.redirect) {
        window.location.href = json.redirect;
      }
    });
})();