← Developer documentation home

Integration Best Practices

Build a reliable QixolPromo integration with practical guidance for checkout, coupon validation, promotion results, order confirmation and error handling.

Use this guide alongside Getting Started and the API Reference. It explains the decisions that matter when connecting QixolPromo to your commerce application.

1. Integration architecture and security

Integrate through a trusted server-side service. Store each company's confidential Services Interaction Key securely and use it as the companyKey URL segment; do not expose it in browser JavaScript, public repositories or logs. Evaluation keys may be obtained through the Portal; production keys are provided by Qixol.

Configure Evaluation/Development and Production base URLs, company keys, timeouts and monitoring separately. Production companies have IP restrictions enabled by default. Evaluation/Development companies are not subject to those IP restrictions. In the Portal, use Configuration → Permitted IP Addresses: Basket Service Access covers Basket Evaluation; Data Management Service Access covers Configuration, Import and Export. Changes may take up to 24 hours. Contact Qixol if an exceptional production exemption is required.

Use HTTPS and avoid sending customer names, email addresses or other personal contact details in basket payloads. Use a customer identifier or group only where needed for promotion eligibility. Redact keys, codes and customer identifiers from operational logs.

2. Choose when to evaluate a basket

Use Validate Basket (10300) at meaningful points in the customer journey: when products or quantities change, a coupon is added, delivery choices change, or checkout needs an up-to-date promotional total. Avoid firing an API call for every keystroke or purely cosmetic UI event.

Typical flow:

  1. Build the current basket in your commerce application.
  2. Submit an unconfirmed basket for promotion evaluation.
  3. Interpret the returned basket and promotion outcome; present prices and messages consistently.
  4. Re-evaluate when a change could affect eligibility.
  5. Submit the confirmed basket only at the agreed completed-order stage.

Not every application needs the same evaluation frequency. Balance responsiveness with service limits and business requirements.

3. Preserve basket identity and sale date

Assign one unique basket id per commerce transaction and reuse that same ID for every evaluation, resubmission and confirmation, including when the basket changes. Keep the basket sale date/time consistent across the shopping session and use UTC unless the operation specifies otherwise. Maintain stable line IDs for corresponding items where practical; the response may split or generate lines.

Do not create a fresh basket ID as a generic retry mechanism. See Validate Basket (10300) for the exact request model.

4. Process the returned basket, not just a discount total

The evaluated basket can differ from the submitted basket. Depending on configured promotions, the service may apply discounts, split a line when only part of a quantity qualifies, add free-gift lines, alter delivery discounts or return additional attributes and promotion details.

Example: A submitted line for three units might be represented by multiple returned lines if only one unit qualifies for a discount. Your UI may need to regroup those lines for display, without losing the individual promotional outcomes.

Do not assume one returned line always maps one-to-one to one submitted line. Use the response structures and field definitions in the Validate Basket API Reference; test the handling of split lines, free gifts, delivery charges and manually discounted items. items[].manualdiscount represents the total manual discount for that line, not a per-unit discount.

5. Handle coupon codes in the basket lifecycle

Validate Coupon Code (10200) can be used to check a code when a customer enters it. A successful independent validation does not necessarily mean the associated promotion will apply to the current basket; eligibility may depend on products, customer context, timing and other conditions.

Include applicable coupon codes in subsequent basket evaluations and display the outcome returned for the actual basket. Treat coupon redemption and any persistent effects of confirmation separately from preliminary validation.

6. Distinguish unconfirmed and confirmed transactions

Use confirmed: false for shopping and checkout previews. Submit confirmed: true at the appropriate completed-order stage agreed with your commerce/payment workflow; the original integration guide recommends confirmation after payment, but this is an integration workflow recommendation rather than a universal API protocol prerequisite.

Confirmation records persistent effects, including coupon utilisation, voucher issuance and promotion-use activity. For the same basket ID, coupons already utilised and vouchers already issued are not processed a second time on subsequent confirmed submissions, even if basket contents have changed. This is specific duplicate protection, not a promise of full request idempotency.

If an amended confirmed basket no longer qualifies for a previous award, the engine does not automatically reverse that earlier effect. The integrating system must handle any required adjustment or reversal.

7. Plan safe retries and uncertain outcomes

Use bounded retries with backoff for transient transport failures and suitable non-persistent operations. On TR999, reduce request rate and retry after a delay. Do not assume a Retry-After header or a fixed retry interval unless confirmed by the deployed service.

For an uncertain confirmed basket outcome, preserve the original basket ID and reconcile the order and recorded effects before resubmitting. Reusing the same ID protects against duplicate coupon utilisation and voucher issuance, but other side effects and recovery procedures must be considered. Keep your own order identifier and confirmation audit trail.

8. Check application results as well as HTTP responses

HTTP 200 can mean the service processed a request without guaranteeing that the requested business operation succeeded. Inspect the application response, especially summary.result and summary.messages, and handle returned validation or business errors appropriately.

Keep HTTP transport failures (network, timeout, HTTP status) distinct from QixolPromo application-level outcomes. Log a safe correlation reference, operation, environment, elapsed time and relevant response summary for diagnosis.

Use the documented Response Codes & Messages catalogue and the relevant operation response schema when handling specific application messages.

9. Respect throttling and performance limits

In Evaluation/Development, Validate Basket (10300) and Validate Coupon Code (10200) share a default limit of 10 requests per second. The limit can be configured for your company. These application-level limits do not apply to Production Basket requests.

Export requests are limited to 5 calls per second. This limit applies to all companies. Pace requests and use a controlled retry after throttling. Import requests are queued for asynchronous processing and are not throttled.

Handle application code TR999 if returned. Avoid tight retry loops and confirm current limits with Qixol before load testing or production rollout.

10. Use JSON and XML deliberately

Use the operation's documented JSON or XML request structure and XSD/schema. Set Content-Type to match the actual request body. Do not assume that the Accept header alone selects the response format: the response format can depend on the service endpoint and request configuration. Inspect the actual response Content-Type and parse accordingly.

XML can represent attributes and text content differently from JSON; use the XML Reference Guides rather than mechanically translating field names. Test the actual outbound body and headers of generated clients.

11. Test before production rollout

Cover ordinary discounts and no-promotion outcomes; invalid and valid coupon codes; split lines; free gifts; delivery discounts; manual discounts; customer/store/channel attributes; application errors; timeouts; throttling; and the confirmed-order workflow.

Verify that the integration displays returned prices and messages correctly and that retries cannot accidentally duplicate persistent activity. Test environment configuration, permitted outbound IPs, key handling, monitoring, and operational recovery procedures.

12. Troubleshooting checklist

Symptom First checks
No promotion applied Product codes, dates, basket attributes, store/channel, promotion eligibility and response messages
Coupon accepted but no basket discount Whether the coupon's promotion conditions are met by the current basket
Unexpected basket lines Split-line and free-gift processing; do not assume one-to-one line mapping
HTTP 200 but operation unsuccessful summary.result and summary.messages
Throttling response Request rate, concurrency, backoff and environment limits
XML request rejected Actual XML body, Content-Type, element structure and XSD compatibility
Confirmed request timed out Do not immediately retry; reconcile the original outcome first

13. Next steps and reference material

Start with Getting Started, then consult the API Reference, API Overview, Response Codes & Messages and XML Reference Guides. These guides share the same operational policy; the API Reference contains operation-specific request and response schemas.

Asynchronous imports and data synchronisation

All five Import operations enqueue work. An accepted request does not mean processing has completed. Use the Portal Import Log to review Pending, In Progress, Success, Failed, Warnings and Cancelled; warnings can include errors. There is no documented Import status API or guaranteed returned job ID.

Use Export data for catalogue and promotion merchandising where appropriate, often via a local cache. Synchronise product and attribute data when required for promotion eligibility. Company configuration (including Best Deal layering) can change results; extension-specific settings such as a 1,000-record sync batch size are not general API limits.