EVIPartner API
Store

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.

To get started you only need an API key — request it from us. Everything else is below.

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Response 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. 1. POST /verify — check the code is valid and unused.
  2. 2. Collect the account credential the product needs (product.kind from /verify): ChatGPT (chatgpt_session) — the session JSON from chatgpt.com/api/auth/session (personal account, free plan); Grok (grok_cookie) — the grok.com sso cookie, see Grok.
  3. 3. POST /redeem with code + session_info.
  4. 4. Poll GET /orders/{code} until status is done or failed.
  5. 5. Some orders need one extra step: ChatGPT may return a customerAction (Stripe); any product may return reauthRequired (credential rejected → send a fresh one to /reauth, the code is not consumed). For Grok it may come with reauthHint — which account to ask for instead: new_account or already_subscribed, see Grok. Handle it, then keep polling — only done means delivered.

Endpoints

GET/config

Capabilities 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" }
] } }
POST/verify

Body { "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.

POST/redeem

Body { "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…" } }
POST/reauth

Body { "code", "session_info" } with a fresh credential after reauthRequired: true. Same response as /redeem; a rejected attempt doesn't consume the code.

GET/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" } }
POST/cdk-status

Body { "code" } → { "data": { "state": "unused" | "processing" | "done" } }.

POST/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 — customerAction never appears.
  • The account email isn't known in advance; it appears as account in /orders/{code} once the order is done.
  • 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} returns reauthRequired: true and reauthHint: "already_subscribed" (usually with status: "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

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..."}'