Connect an AI app
Connect an AI app to a merchant's shop with OAuth, ask for the right scopes and stay inside the credit limit.
Beta
The Merchant API is in Beta. Connections are opened and paused by ShopEazy.
This recipe is for an app that acts on a merchant's shop for them: a chat assistant, an agent, a back-office tool. The merchant connects your app once, chooses what it may do, and can disconnect it whenever they like.
The mechanics are in Merchant OAuth and Quickstart: Merchant. This page is the order to do things in.
1. Decide what to ask for
Ask for the least you need. The merchant can only narrow your request, so an app that asks for everything looks like one that wants everything.
| Your app does | Ask for |
|---|---|
| Reports on the shop | store:read, orders:read |
| Keeps listings up to date | store:read, listings:read, listings:write |
| Handles orders and bookings | store:read, orders:read, orders:write, bookings:write |
| Answers customer messages | store:read, customers:read, messages:read, messages:send |
| Writes copy, makes images or designs the shop | ai:spend, and design:write for the design |
Four scopes are opt-in, off by default and switched on one at a time by the merchant: orders:refund, billing:write, ai:spend and delivery:write. Ask for them only when your app needs them. The consent screen warns the merchant that refunds and plan changes always ask first, so build your app to ask the person before it does either.
The full list is in Merchant OAuth.
2. Send the merchant to the consent screen
Ask for the Merchant API with resource=https://api.shopeazy.co, here and again on the token request. Without it the token is for the console and the API refuses it. Your app can find the authorization server by reading https://api.shopeazy.co/.well-known/oauth-protected-resource. A 401 from the API carries a WWW-Authenticate header that points to the same place, so an app that gets one can start the sign-in from it.
https://app.shopeazy.co/oauth/authorize
?response_type=code
&client_id=<client_id>
&redirect_uri=<redirect_uri>
&code_challenge=<code_challenge>
&code_challenge_method=S256
&resource=https%3A%2F%2Fapi.shopeazy.co
&scope=store%3Aread%20listings%3Aread%20listings%3Awrite
&state=<random state>The merchant:
- Signs in, or signs up if they are new to ShopEazy.
- Picks the business and the stores to connect.
- Chooses what to allow, within what you asked for and what their role holds.
- Sets the money limits, if you asked for those scopes.
- Selects Allow.
Then exchange the code for tokens, as in the quickstart, sending the same resource. Keep the refresh token somewhere safe. It lasts 60 days and every refresh issues a new one.
3. Read what you were granted
The merchant may have allowed less than you asked for. Call getSession first.
curl https://api.shopeazy.co/v1/merchant/session \
-H "Authorization: Bearer <access_token>"Read data.grant:
{
"id": "grant_123",
"clientName": "Orders assistant",
"scopes": ["store:read", "listings:read", "listings:write"],
"storeIds": ["store_123"],
"standingApprovals": { "aiCreditsPerMonth": 100 }
}scopesis what you may do. Do not offer a tool the token has no scope for.storeIdsis the stores you may act on.nullmeans every store the person can reach. Any other store is404 store_not_found.standingApprovalsis what the merchant lets you do without asking each time. See below.
A call without the scope answers 403 forbidden. Your real power is also the person's role today and the plan, so a call can be refused even when the scope was granted.
4. Make calls
- Send
Authorization: Bearer <access_token>on every call. - Every write needs an
Idempotency-Key. Make one per action and reuse it on retries. See Idempotency. - A
401 invalid_tokenmeans the access token expired, the merchant changed or removed the connection, or the token was issued for another server. TheWWW-Authenticateheader says which, inerror_description. Refresh, and check your authorize request sentresource=https://api.shopeazy.co. If the refresh fails withinvalid_grant, the merchant has to connect again.
5. Stay inside the credit limit
A connected app spends the business's credits only up to a monthly limit the merchant sets for it, in the console under Settings, then AI apps. The limit is standingApprovals.aiCreditsPerMonth on the session. The month is a calendar month in UTC.
These operations spend credits: draftProduct, generateProductCopy, generateImage, designForMe, buildPageWithAi, startStudioMake and sendCampaign (which costs 1 credit for every 10 recipients).
A call that would take the connection past its limit answers 403 over_credit_limit and spends nothing:
{
"error": {
"code": "over_credit_limit",
"message": "<a sentence written for the merchant>",
"requestId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}
}Do not retry. Tell the merchant the app has used its monthly limit and that they can raise it in Settings, then AI apps. The business may still have credits. A connection with no limit set is held only by the business's balance.
Two more limits can stop an AI call:
- A store's daily allowance. 300 AI generations a day, and 100 email sends. Past it the call is
429 rate_limited. Wait forRetry-After. See Rate limits. - Not enough credits.
403 insufficient_credits. The merchant buys more.
6. Money moves ask first
Other standing approvals are the merchant's to give, never the app's:
courierMaxCents. A courier booking up to this price goes ahead without asking. Above it,bookCollectionanswers403 over_courier_limit.confirmBookingRequests. Booking requests can be confirmed without asking. Declines still ask.
For everything else that moves money, such as a refund or a plan change, ask the person in your own interface before you call.
7. What an AI app cannot do
Some operations can only be done in the ShopEazy app. They cover the bank details shoppers pay into, payment-provider and courier credentials, the team's roles, closing an account and Storefront API keys. Your app gets 403 forbidden with "This can only be done in the ShopEazy app.", whatever it was granted. A step that needs the merchant in a browser, such as entering payment credentials, is 422 needs_browser. In both cases, tell the merchant to do that step in the ShopEazy app.
8. Know when you were disconnected
The merchant can disconnect your app in Settings, then AI apps. Every token stops working at once. Your next call is 401 invalid_token, and a refresh answers invalid_grant. Show the merchant a clear way to connect again.