OpenCart

OpenCart's core API only creates orders, with no catalogue or inventory endpoints: real read paths are the database, an extension or an aggregator.

OpenCart is a free, open source, self-hosted PHP shopping cart, GPL licensed, widely used by small merchants in South and South East Asia, Eastern Europe and the Middle East precisely because it costs nothing and runs on cheap shared hosting. For a connector the important discovery is that OpenCart's "API" is not a data API. The routes under index.php?route=api/... exist so the admin order editor and headless checkouts can build and confirm a cart: set a customer, add products to a cart, set addresses and shipping, confirm an order. There is no products endpoint, no inventory endpoint, no order listing endpoint and no webhooks. The official documentation contains exactly one API page, and it is about generating credentials. Everything else a commerce database needs comes from the database, a third party extension, or an aggregator that has already written the plugin.

At a glance

What it is

OpenCart is a single-merchant cart, not a marketplace and not a SaaS. The merchant installs it on their own hosting, so every store is a separate deployment with its own domain, its own database and its own PHP version. Two lines are in production: 3.0.x, still very common, and 4.x, the current rewrite with namespaced PHP. They differ enough in the API area that a connector needs two code paths.

A single OpenCart install can serve several storefronts through the multi-store feature, which is why store_id appears on orders and on the product-to-store mapping. Extensions come from the OpenCart marketplace and from GitHub, and the quality range is very wide.

Because it is self-hosted, there is no platform-level rate limit, no partner programme, no sandbox and no support contract. The constraint is the merchant's own server and whether they will install anything.

API access

The merchant creates the credential in their own admin at System, Users, APIs. The documented fields:

  • API Username, a unique identifier for the key, 3 to 20 characters.
  • API Key, generated by OpenCart, 64 to 256 characters. The documentation warns that you cannot see it again after saving, so capture it at creation.
  • Allowed IPs, the static IPs of your external servers. This is not optional in practice: the core checks the caller's address against this list on every request and rejects anything else. OpenCart shows the current IP on the form to make this easier.
  • Status, to enable or disable the key without deleting it.
  • History, an audit trail of API activity with the endpoint accessed, the source IP and a timestamp.

There are no official SDKs. There is no partner or app programme. There is nothing to apply for: if you can get the merchant to create a key and allow-list your IP, you have access.

Warning

The IP allow list is the single biggest operational constraint. A connector running on autoscaled or serverless infrastructure with changing egress addresses will fail intermittently and confusingly. Pin your egress behind a static NAT address before onboarding an OpenCart merchant.

Authentication

OpenCart 3.0.x

  1. POST to index.php?route=api/login with form fields key and optionally username. When username is omitted the core falls back to the literal username Default.
  2. The core looks up the key, then checks the caller's REMOTE_ADDR against the rows in oc_api_ip for that API user. A mismatch returns an error naming the rejected address.
  3. On success it starts a PHP session, records it in oc_api_session, and returns the session ID as api_token.
  4. Pass that token as an api_token query parameter on every subsequent api/... route.
curl -X POST 'https://shop.example.com/index.php?route=api/login' \
  -d "username=Default" -d "key=${API_KEY}"
{ "success": "<text_success language string>", "api_token": "<php session id>" }
curl 'https://shop.example.com/index.php?route=api/order/info&api_token=<php session id>&order_id=42'

The token is a PHP session ID, so it expires with the session and is cleaned up by cleanSessions(). Treat it as short-lived and re-login on failure.

OpenCart 4.x

The login controller is gone. In the 4.x.x.x branch, upload/catalog/controller/api/ contains only affiliate, cart, customer, order, payment_address, payment_method, shipping_address, shipping_method and subscription. A login(username, key) method still exists on upload/catalog/model/setting/api.php, but no core controller in that branch was found calling it.

What does exist is the validation side, in upload/catalog/controller/startup/session.php: when the route starts with api/ and an api_token query parameter is present, the core looks the token up with getApiByToken(), which joins oc_api, oc_api_session and oc_api_ip and requires the API user to be active and the caller's IP to match, then resumes that session. So in 4.x the session is created on the admin side and the token is handed to the integration, rather than minted by a login call.

Note

Verify this against the exact 4.x point release you target. The API area has moved between 4.0, 4.1 and later patches, and the observation above is from reading the 4.x.x.x branch head. If the merchant's build has an api/account/login route, prefer it.

Objects we can read

Very little, and that is the finding.

Orders

3.0.x has upload/catalog/controller/api/order.php with five methods: add(), edit(), delete(), info() and history(). info and history are the only genuine read operations anywhere in the core API, and both take a single order_id. There is no listing endpoint, no date filter and no pagination, so you cannot discover new orders through the API at all.

4.x replaced that with a single index() that dispatches on a call query parameter. The allowed calls read from the source are customer, cart, product_add, payment_address, shipping_address, shipping_method, shipping_methods, payment_method, payment_methods, extension, affiliate and confirm. That is a checkout builder, not an order reader.

Products, inventory, customers, shipments, returns, settlements

None of these exist in the core API on either branch. The 3.x controller set is cart, coupon, currency, customer, login, order, payment, reward, shipping, voucher; the 4.x set is listed above. customer sets the customer on a cart in progress, it does not list customers.

What the actual read paths are

  1. Direct database access. OpenCart's schema is stable and documented in the install SQL. The tables that matter:

    • oc_order: order_id, invoice_no, invoice_prefix, store_id, store_name, customer_id, customer_group_id, firstname, lastname, email, telephone, the payment_* and shipping_* address blocks, payment_method, payment_code, shipping_method, shipping_code, comment, total, order_status_id, commission, tracking, currency_code, currency_value, date_added, date_modified.
    • oc_order_product: order_product_id, order_id, product_id, name, model, quantity, price, total, tax, reward.
    • oc_order_total: the itemised sub-total, shipping, tax and grand total rows.
    • oc_order_history: the status trail, one row per order_status_id change with a date.
    • oc_product: product_id, model, sku, upc, ean, jan, isbn, mpn, location, quantity, stock_status_id, image, manufacturer_id, price, tax_class_id, date_available, weight, length, width, height, subtract, minimum, status, date_added, date_modified.
    • oc_product_description for localised name, description and meta; oc_product_to_store for multi-store visibility; oc_product_special and oc_product_discount for promotional prices.

    This is the only route that gives you a complete, filterable, incremental read (date_modified on both oc_order and oc_product). It requires database credentials, which many hosts will not expose, and it bypasses every business rule in the application, so treat it as read-only.

  2. A marketplace or GitHub extension that adds real REST endpoints.

  3. An aggregator that has already written the plugin, such as EasyEcom, Unicommerce or Vinculum, where the integration is configured with store URL plus API credentials rather than built by you.

Writing back: listings, price and stock

Not possible through the core API. There is no product, price or stock endpoint on either branch.

What the core API can do is build and confirm an order: set the customer, add products to a cart, set payment and shipping addresses, pick a shipping and payment method, then confirm. In 3.x that is api/cart, api/customer, api/shipping, api/payment and api/order/add; in 4.x it is the call values on api/order. This is useful if you are pushing orders into OpenCart from a marketplace, and useless for catalogue synchronisation.

For listing, price and stock write-back the options are the same three as for reads. Direct SQL writes against oc_product.quantity and oc_product.price will work but skip OpenCart's cache invalidation and its stock subtraction logic, so prefer an extension that goes through the model layer. Bulk catalogue changes are more commonly done in the admin with a CSV import extension than over any API.

Extensions that add a real API

No first-party option exists, so this is third party territory. Examples visible on GitHub, listed so you can evaluate them rather than as recommendations:

  • iSenseLabs/OpenCartAPI, a client library that talks to OpenCart's own REST routes.
  • opencartbrasil/opencart-rest-api, a REST API for OpenCart 2.1 and above.
  • Chren/OpenCartRestApi, a RESTful API for OpenCart.
  • maxpoletaev/opencart-webapi, marked deprecated by its author.

There are also commercial REST extensions sold through the OpenCart marketplace. Before adopting any of them, read the source for the endpoints you need, check the last commit date against the merchant's OpenCart version, and confirm it respects the IP allow list and the API user status rather than adding a parallel credential.

Warning

Be sceptical of any repository or document that claims to enumerate an OpenCart REST API for products, inventory or order listing. OpenCart's own documentation publishes no endpoint reference, so such lists are either describing a specific third party extension (name it) or are fabricated. Verify every endpoint against source you can read.

Webhooks and notifications

None. OpenCart has no outbound webhook mechanism.

What it does have is an internal event system, documented in the developer guide, where an extension registers a trigger on a model or controller method and runs PHP before or after it. That is the correct place to build a push notification: a small custom extension that hooks order creation and status change and POSTs to your endpoint. OpenCart also has a scheduled task and cron job mechanism for periodic work.

Without that, polling is the only option, and the core API gives you nothing to poll because there is no listing endpoint. If you are limited to the API, you can only fetch orders whose IDs you already know. In practice: poll the database on oc_order.date_modified and oc_product.date_modified, or install an extension.

Rate limits and pagination

There are no platform rate limits, because there is no platform. The limits are the merchant's PHP process count, their shared hosting CPU allowance and any WAF in front of the store. Be conservative and serialise requests; a shared-hosting OpenCart will fall over long before a SaaS would.

There is no pagination anywhere in the core API, because there is no listing endpoint to paginate. Database reads paginate with ordinary SQL on date_modified plus a primary key tiebreak.

The security gate is the IP allow list plus the API user status, both checked per request, and the API history table gives the merchant an audit trail of what you called.

Mapping to the unified model

Since the practical source is the database, the mapping is to tables rather than to endpoints.

Gaps and open questions

  • The core API publishes no endpoint reference. Everything above about routes comes from reading the source on the 3.0.x.x and 4.x.x.x branches, not from documentation.
  • There is no way to list or discover orders through the core API, which makes an API-only connector impossible.
  • No catalogue, inventory, customer, shipment, settlement or location endpoints exist in core.
  • The 4.x authentication path could not be fully traced: the 3.x api/login controller is absent and model_setting_api->login() appears unused by any core controller in the branch read. Confirm against the merchant's exact point release.
  • oc_order.order_status_id values are merchant-configurable, so no fixed status map can ship with the connector.
  • No webhooks, and no first-party extension that adds them.
  • Third party REST extensions were not evaluated for correctness or security in this pass; the list above is examples found on GitHub, not recommendations.
  • The oc_return table set was not read in detail for this note.

Sources