Changelog

Every change to the API, the SDK and these docs. The API is additive within v1: a field may be added, never removed or renamed.

  1. API

    Rewards are spent where their program runs

    A program runs in one or more places. In the dashboard a business now ticks where each rewards program runs: its till, its online store, the Developer API. Customers earn the program's reward in each of those places and can spend it in any of them.

    The API lists and redeems the rewards it can spend. GET /v1/customers/{id}/rewards returns the rewards of programs that run on the Developer API. A reward from a program that runs only somewhere else is not listed, does not hold back POST /v1/earn with ACTIVE_REWARD_EXISTS, and answers 404 REWARD_NOT_FOUND on POST /v1/redeem. Before, the API listed and redeemed every reward a customer held at the business.

    What to check. If your customers earn in your app and spend at the counter, or the other way round, the program needs both ticked under Where it runs (see Going live). No request or response changes shape, and there is no new error code.

  2. Docs

    A support address for developers

    Write to developers@trovy.ca. Questions about the API, the sign-up form or the SDK now have their own inbox, answered by the people who build them. The guides, the error messages that tell you to get in touch (API_KEY_DISABLED, API_NOT_ENABLED, ORDER_AMBIGUOUS, INTERNAL_ERROR) and the Developer API panel in the Trovy dashboard all give this address. Nothing about your integration needs to change.

  3. API

    Switching instant rewards off

    products on your business. GET /v1/business now reports which products your business has switched on, starting with products.instantRewards. A business switches its products in its dashboard. Read them once at setup, as you do currency.

    403 REWARDS_NOT_ENABLED. With instant rewards switched off, POST /v1/earn records nothing and answers this code. A retry of an order that earned before the switch still gets its original answer. Rewards customers already hold stay redeemable: rewards reads, POST /v1/redeem and refunds work as before.

    Both are additions to the contract; nothing else changes.

  4. Docs

    The checkout decision in full, going live, and mobile apps

    At checkout. Rewards now has all three branches: a usable reward the order reaches (offer it), a usable reward the order does not reach or the customer declines (record nothing), and no usable reward (earn). It also says what the order amount should cover, that a reward is used whole, what a redeem refused after capture leaves behind, and how to handle orders that are cancelled, reduced or increased after payment.

    Going live. A new step in the Sandbox guide: link your rewards program to the Developer API in Campaigns. Switching the API on does not, and until you do every earn answers 409 NO_ACTIVE_PROGRAM.

    Mobile apps and who can join. Customers and the widget has a recipe for the sign-up form in a WebView, and says which phone numbers can join.

    Samples you can paste. The quickstart's curl samples set their own idempotency key, the rewards sample checks usable and the minimum, and every TypeScript sample now constructs its client from your key.

  5. API

    A spent reward says so

    Redeeming a spent or expired reward. POST /v1/redeem with a reward that was already redeemed now answers 409 REWARD_ALREADY_REDEEMED, and one past its end 409 REWARD_EXPIRED, as Rewards always said. When the customer also held a newer usable reward, which is usual after a redeem on a recurring program, both used to answer NOT_OLDEST_REWARD, naming that newer reward as the one to apply, which on a double-submitted checkout would discount the same order twice.

    Wording. The reference names operations by their routes (POST /v1/redeem) rather than their operation ids, says what to send as an Idempotency-Key the way the idempotency guide does, and lists the sandbox's fictional numbers as a US or Canadian area code, or 721, followed by 555-0100 to 555-0199.

  6. Docs

    Next.js and React in the SDK guide, and the sign-up form's codes

    The SDK guide covers the whole package. @trovy/sdk has four entry points, and the TypeScript SDK guide used to describe only the API client. It now covers <TrovySignup> from @trovy/sdk/react, createLinkHandler from @trovy/sdk/next and mount from @trovy/sdk/widget, with a Next.js integration in three steps and how to test the link route.

    Every code the sign-up form can report. Errors lists what onError can carry besides the /v1 codes: the form's own, and those of the widget's endpoints, such as PHONE_NOT_SUPPORTED, CODE_INVALID and TOO_MANY_REQUESTS.

  7. Docs

    Sign-up form fixes, and the texts your customers get

    Back to the number, and on again. A customer who pressed "Use a different number" and then sent the same number again was refused with "Too many messages", although the code already sent still worked. The form now returns to that code. A different number still gets a new one.

    Sandbox wording. Above the code it shows, the sandbox form now says "Here is the code we would have texted" rather than "We texted", and the preview wraps on a phone instead of running off the edge. The phone field no longer takes focus when the page loads.

    v1.js names the cause. When the form does not load within ten seconds, the script-tag loader's WIDGET_UNAVAILABLE message now names the page's origin and where to list it, as @trovy/sdk already did.

    Guides. Customers and the widget lists every text Trovy sends your customers, including the welcome text, and where to change the wording. Rewards covers first-order-only programs (FIRST_ORDER_ONLY) and says what to do when the earn after a refused redeem is itself refused. The quickstart has a section for integrations that do not use TypeScript.

  8. API

    Make your own sandbox, and go live without asking

    Getting started no longer involves an email to us.

    Your own sandbox. In the dashboard, Integrations → Developer API → Create sandbox makes a test copy of your business: your currency and timezone, a copy of your program's rules, one customer already linked, and a page to create test keys on. One per business, and anyone on your team can make it. See the Sandbox guide.

    Go live yourself. Your organization's owner switches the Developer API on from the same page.

    A sandbox cannot reach a real person. Its sign-up form accepts only fictional phone numbers (any area code, then 555-0100 to 555-0199) and shows you the code on screen; 000000 also works, for automated tests. Each host now takes only its own keys: api.sandbox.trovy.ca refuses live keys and api.trovy.ca refuses test keys, both as API_KEY_INVALID.

    Fixes to the ledger.

    • Refunding an order that redeemed a reward now claws back the new reward that order earned. It used to leave it in place.
    • Two requests racing to record the same orderId under different keys: the loser now gets DUPLICATE_ORDER, not IDEMPOTENCY_MISMATCH.

    Guides corrected. Four of them described behaviour the API does not have. Redeem after the payment succeeds, not before: a redeemed reward is never handed back, even by a refund. An earn for a customer with a usable reward waiting is 409 ACTIVE_REWARD_EXISTS. A phone number that is not a member of your business is a 404 from the lookup, not linked: false. And a refund needs its own idempotency key, not its order's.

  9. API

    The sign-up widget tells you when it cannot load

    WIDGET_UNAVAILABLE. If the form has not appeared ten seconds after Trovy.mount, the loader hides the frame and calls onError with WIDGET_UNAVAILABLE. Until now a page whose origin was not listed, a revoked key and an outage were all silent: the browser drew its own error box and your code heard nothing. It is not final — a frame that was only slow is shown again — so keep the widget mounted and show your own fallback.

    NETWORK_ERROR. When the customer's browser gets no answer from Trovy, the form says so in plain words and onError fires. It used to show the browser's own "Failed to fetch" and tell your page nothing.

    Allowed origins are stored the way a browser reports them. https://shop.example:443 is saved as https://shop.example. Listed with the default port, the form used to render and then deliver its token to nobody, because no browser ever reports :443. Origins already saved that way are matched correctly without you changing anything. https://localhost is now refused on a live business, as http://localhost always was.

    No form without somewhere to send the result. The frame renders only inside a page whose origin is on the key's list. Opened on its own, or embedded somewhere unlisted, it shows the unavailable page instead of a form whose sign-ups you would never hear about.

    Business names with typographic characters. A business called Joe’s — with the apostrophe a phone keyboard types — got an error page instead of a form. Fixed.

    Errors about your key stay with you. A customer whose form hits a revoked or disabled key now reads "Sign-up isn't available right now"; the real code and message still reach onError.

    Resend. A refused "send a new code" now holds the button for as long as the API said to wait.

  10. API

    API v1 and the TypeScript SDK

    The first public version of the Trovy API. Operations covering rewards and customer linking, plus the sign-up widget and @trovy/sdk.

    Rewards. POST /v1/earn, /redeem and /refunds record orders against the same ledger the in-store counter writes to, so a business's dashboard and reports read both alike. An order either earns or redeems, never both.

    Customers. The sign-up widget is the only way a customer joins. It hands your page a single-use token, and POST /v1/customers/link exchanges it for a customer id that means nothing at any other business.

    Idempotency. Required on every write. A replay returns the first result; a reused key with a different body is refused with IDEMPOTENCY_MISMATCH.

    Currency. GET /v1/business reports the unit every …Cents field is counted in. A business has one currency and it cannot change once it has transacted.

    Sandbox. api.sandbox.trovy.ca, with its own keys, a seeded business, and texts returned as previews instead of sent.