EVI Partner API
Integrate EVI activation into your own site or app. You buy EVI codes from us and sell them to your users; they redeem them through this API — including the Stripe payment verification when it is required.
Base URL & auth
Base URL: https://api.evishopai.com/v1. Call it only from your server — your users' devices talk to your backend, and your backend talks to this API. Currently supported: ChatGPT (Plus / Go / Pro) and Grok (Plus / Premium / Super / Ultra, including “50% off offer” plans). The live list of products is in /config.
Authorization: Bearer evi_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxResponse format
Success returns { "data": { … } }; failure returns a stable code plus a human message:
// success
{ "data": { "status": "valid" } }
// failure (HTTP 4xx/5xx)
{ "code": "cdk_not_found", "message": "Code not found" }Branch on code, not on message. 401 = bad key · 404 = code not found · 409 = state conflict · 429 = rate limited · 5xx = retry later.
Flow
- 1.
POST /verify— check the code is valid and unused. - 2. Collect the account credential the product needs (
product.kindfrom/verify): ChatGPT (chatgpt_session) — the session JSON fromchatgpt.com/api/auth/session(personal account,freeplan); Grok (grok_cookie) — the grok.comssocookie, see Grok. - 3.
POST /redeemwithcode+session_info. - 4. Poll
GET /orders/{code}untilstatusisdoneorfailed. - 5. Some orders need one extra step: ChatGPT may return a
customerAction(Stripe); any product may returnreauthRequired(credential rejected → send a fresh one to/reauth, the code is not consumed). For Grok it may come withreauthHint— which account to ask for instead:new_accountoralready_subscribed, see Grok. Handle it, then keep polling — onlydonemeans delivered.
Endpoints
/configCapabilities and available products.
{ "data": { "customerActionSupported": true, "kinds": ["chatgpt_session", "grok_cookie"], "products": [
{ "id": 4, "name": "ChatGPT Plus — 1 month", "kind": "chatgpt_session" },
{ "id": 33, "name": "Grok Premium — 1 month", "kind": "grok_cookie" }
] } }/verifyBody { "code": "EGPLUS-XXXX-XXXX-XXXX" }. Returns status: valid · used · invalid.
{ "data": { "status": "valid", "product": { "name": "ChatGPT Plus — 1 month", "kind": "chatgpt_session" } } }product.kind tells you which credential to collect: chatgpt_session or grok_cookie.
Codes come in two formats: EVI-XXXX-XXXX-XXXX-XXXX and the newer EGPLUS-7KQ2-M9XA-3TPL (a product prefix plus a random part). Both work — treat a code as an opaque string and don't validate its prefix.
/redeemBody { "code", "session_info" }. session_info is the full account session JSON for ChatGPT, or the grok.com sso cookie for Grok (formats) — a string, used only for this activation, never stored, mask it in your logs. We check the token live first; an expired / invalid / already-subscribed account is rejected without consuming the code.
status: processing · done · failed · used. used = the code was already activated earlier — it is spent, do not deliver again. Re-submitting any spent code always returns used, never a fresh done. ChatGPT: a rejected/expired session comes back with reauthRequired: true — send a fresh session to /reauth (code not consumed).
{ "data": { "id": "EGPLUS-XXXX-XXXX-XXXX", "status": "processing", "message": "Activation started…" } }
// already activated earlier — spent, do NOT re-deliver:
{ "data": { "id": "EGPLUS-…", "status": "used", "message": "This code has already been used…" } }/reauthBody { "code", "session_info" } with a fresh credential after reauthRequired: true. Same response as /redeem; a rejected attempt doesn't consume the code.
/orders/{code}status: done · processing · failed. customerAction appears only while a Stripe check is pending (disappearing ≠ success). ChatGPT: reauthRequired: true means the session expired or was rejected (incl. mid-processing) — send a fresh session to /reauth.
account — the email of the account the plan goes to, when known (ChatGPT: from the session; Grok: once done). queue — { "ahead": 2, "etaMs": 420000 } while the order waits in line, when available.
note — a human-readable status text in English (on failed: what happened and what to do). You may show it to the user, but branch on status, reauthRequired and reauthHint, not on the text. reauthRequired with a reauthHint is repeated in every response until you send new data to /reauth.
{ "data": { "id": "EGPLUS-…", "status": "processing", "customerAction": { "type": "stripe_next_action", "actionId": "…", "expiresAt": 1788994694219 } } }
{ "data": { "id": "EGPLUS-…", "status": "done", "account": "user@example.com" } }/cdk-statusBody { "code" } → { "data": { "state": "unused" | "processing" | "done" } }.
/customer-action/{start|complete|recheck}Stripe verification proxy — see Stripe payment verification.
Grok
Products with kind: "grok_cookie". session_info is the user's grok.com login cookie, in any of these forms: the value of the sso cookie (eyJ…), a Cookie: header string copied from grok.com (sso=…; sso-rw=…), or a cookie export JSON from an extension such as Cookie-Editor.
How the user gets it: on a computer, sign in at grok.com with the account to upgrade → DevTools (F12) → Application (Storage in Firefox) → Cookies → https://grok.com → copy the value of sso. The user should stay signed in until the order is done.
- No Stripe step for Grok —
customerActionnever appears. - The account email isn't known in advance; it appears as
accountin/orders/{code}once the order isdone. - A rejected or expired cookie returns
reauthRequired: true— send a fresh cookie to/reauth. The code is not consumed. - “50% off offer” plans work only on a Grok account that grok.com currently offers 50% off the first month. If the account has no such offer, the response is
status: "failed",reauthRequired: true,reauthHint: "new_account"— the code is not consumed. Ask the user to create a new Grok account (for example in a private window, with a different email), check that its upgrade page shows 50% off the first month, and send that account's cookie to/reauth. Regular Grok plans work on any account without an active subscription. - Account with an active subscription. If the Grok account already has an active subscription, a new plan can't be added to it:
/orders/{code}returnsreauthRequired: trueandreauthHint: "already_subscribed"(usually withstatus: "failed") — the code is not consumed. Ask the user to sign in to a Grok account without an active subscription (or create a new one) and send that account's cookie to/reauth. Another subscribed account gets the same response; the code still isn't consumed.
{ "data": { "id": "EXPREMIUM50-…", "status": "failed", "message": "This code works only on a Grok account that is offered 50% off the first month — …", "reauthRequired": true, "reauthHint": "new_account" } }{ "data": { "id": "EXPREMIUM-…", "status": "failed", "note": "This Grok account already has an active subscription, so a new plan can't be added to it. …", "reauthRequired": true, "reauthHint": "already_subscribed" } }Stripe payment verification
Some activations need the end user to complete a Stripe check (captcha / 3-D Secure). It only happens when /orders/{code} returns a customerAction. The check runs in the user's browser with official Stripe.js. Your backend forwards start / complete / recheck to us with your key and the code — we add the payment identifiers server-side; you and the browser never send them. Never log clientSecret.
Notes & limits
- Keep the API key on your server only. We store only a hash of it, so it is shown to you exactly once — save it. If it leaks, ask us to rotate it (the old key stops working immediately).
- Repeated failed authentication from one IP is throttled (HTTP 429) — fix the key, don't retry in a loop.
- Never log
session_info(sessions and cookies),clientSecret, or full request bodies. - Rate limits per key/min: verify 120 · redeem 60 · reauth 60 · orders 120 · cdk-status 120 · customer-action 20.
- Poll active orders ~every 5s; the order status is the only proof of delivery.
curl
curl https://api.evishopai.com/v1/config -H "Authorization: Bearer evi_live_xxx"
curl -X POST https://api.evishopai.com/v1/redeem \
-H "Authorization: Bearer evi_live_xxx" -H "Content-Type: application/json" \
-d '{"code":"EGPLUS-XXXX-XXXX-XXXX","session_info":"{\"accessToken\":\"ey...\"}"}'
# Grok: session_info is the grok.com sso cookie
curl -X POST https://api.evishopai.com/v1/redeem \
-H "Authorization: Bearer evi_live_xxx" -H "Content-Type: application/json" \
-d '{"code":"EGPLUS-XXXX-XXXX-XXXX","session_info":"eyJ0eXAiOiJKV1Qi..."}'