OAuth Ecart Pay
Connect your platform to Ecart Pay using OAuth 2.0 (Authorization Code flow). This lets your merchants link their Ecart Pay account to your product so you can operate on their behalf — read their API credentials, create orders, and more.
Table of Contents
- 🚀 Getting Started
- 🔑 How the Flow Works
- 1️⃣ Create Your Application
- 2️⃣ Redirect the Merchant to Ecart Pay
- 3️⃣ Receive the Authorization Code
- 4️⃣ Exchange the Code for the Merchant Credentials
- 🔐 Scopes
- 🔄 Updating Scopes & Re-Authorization
- 🏢 Multi-Company Applications
- 🧪 Complete Example
- 🧪 Testing
- 🚀 Going to Production
- 🧰 Error Reference
- 🔎 Resources
🚀 Getting Started
Prerequisites
Before integrating OAuth with Ecart Pay, ensure:
| Requirement | Description |
|---|---|
| Ecart Pay Account | Active account that will own the OAuth application (the partner / platform account). |
| Dashboard Token | An authorization token with the write_oauth_applications scope to create the application. |
| HTTPS Redirect | A redirect URI served over HTTPS where Ecart Pay returns the authorization code. |
| Backend | A server able to keep your client_secret private and exchange the code for a token. |
Base URLs
- Production:
https://ecartpay.com- Sandbox:
https://sandbox.ecartpay.comUse the sandbox while developing. Switch to production only when you are ready to go live.
🔑 How the Flow Works
| Step | Description |
|---|---|
| 1 | You create an OAuth application and receive a client_id and client_secret. |
| 2 | You redirect the merchant to GET /oauth with your client_id and redirect_uri. |
| 3 | The merchant signs in, completes verification (KYC levels 0 → 1) if needed, and grants consent. |
| 4 | Ecart Pay redirects back to your redirect_uri with a single-use ?code=.... |
| 5 | Your backend exchanges the code (+ client_secret) and receives the merchant account_id, public_id, and private_id directly. |
One-Time VerificationA merchant only completes verification once. On later connections, an already verified
merchant sees a short confirmation screen and is returned to your app immediately.
1️⃣ Create Your Application
Create your OAuth application once. The response includes your client_id and
client_secret.
cURL
curl -X POST "https://ecartpay.com/api/oauth/applications" \
-H "Authorization: Bearer <DASHBOARD_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Your App",
"description": "Short description shown on the consent screen",
"logo_url": "https://cdn.yourapp.com/logo.png",
"redirect_url": "https://yourapp.com/oauth/callback",
"scopes": ["read_orders", "write_orders"],
"onboarding": {
"headline": "Connect Your App with Ecart Pay",
"permissions_summary": ["View and create orders"]
}
}'Response 201
{
"id": "665f2a...",
"name": "Your App",
"client_id": "oauth_live_0cba2d6ad48c3e2f451eaa5e3f93cd12",
"client_secret": "secret_4f1c...e9",
"redirect_url": "https://yourapp.com/oauth/callback",
"scopes": ["read_orders", "write_orders", "read_credentials"],
"status": "active"
}
Store Your SecretThe
client_secretis returned only once. Store it securely on your backend.
You can rotate it later withPOST /api/oauth/applications/:id/secret.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Application name shown on the consent screen. |
| redirect_url | string | yes | HTTPS callback URL. Must be matched exactly on redirect. |
| description | string | no | Short description shown on the consent screen. |
| logo_url | string | no | Logo shown on the consent screen. |
| company_id | string | no | Own the application under one of your companies instead of your personal account. See Multi-Company Applications. |
| scopes | array | no | Requested scopes (see Scopes). read_credentials is always added. |
| onboarding.headline | string | no | Custom consent screen title. |
| onboarding.permissions_summary | array | no | Bullet list of permissions shown to the merchant. |
2️⃣ Redirect the Merchant to Ecart Pay
Send the merchant's browser to the OAuth entry point:
https://ecartpay.com/oauth?client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&state=<STATE>
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_id | string | yes | Your application's client id. |
| redirect_uri | string | yes | Must match a whitelisted redirect URI exactly. |
| state | string | recommended | Opaque value echoed back to you; use it for CSRF protection. |
What the Merchant SeesEcart Pay handles sign-in, runs verification (KYC levels 0 and 1) when required, and
shows a consent screen with your app's name, logo, and the permissions you requested.
3️⃣ Receive the Authorization Code
After the merchant grants consent, Ecart Pay redirects to your redirect_uri:
https://yourapp.com/oauth/callback?code=<CODE>&state=<STATE>
Validate and Be Quick
- Verify the returned
statematches the value you sent.- The
codeis single-use and expires in 5 minutes — exchange it promptly.
4️⃣ Exchange the Code for the Merchant Credentials
From your backend, exchange the code for the merchant's API keys. The code goes in the
Authorization header and your secret in the x-secret header.
cURL
curl -X POST "https://ecartpay.com/api/oauth/token?client_id=<CLIENT_ID>" \
-H "Authorization: <CODE>" \
-H "x-secret: <CLIENT_SECRET>" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"redirect_url": "https://yourapp.com/oauth/callback"
}'Response 200
{
"account_id": "665f2a...",
"public_id": "pub_live_...",
"private_id": "prv_live_...",
"scope": "read_orders,write_orders,read_credentials"
}
One-Step ExchangeThe token exchange returns the merchant
account_id,public_id, andprivate_id
directly. Use these keys to operate on the merchant's behalf with the standard
Ecart Pay API (for example, the Orders API).
Store the Keys SecurelyThe
private_idis a secret. Store it encrypted on your backend, just like your
client_secret, and never expose it in the browser.
Request Reference
| Location | Field | Description |
|---|---|---|
| Query | client_id | Your application's client id. |
| Header | Authorization | The authorization code. |
| Header | x-secret | Your client_secret. |
| Body | grant_type | authorization_code. |
| Body | redirect_url | The same redirect URI used in the flow. |
Scope RequiredReturning the credentials requires the
read_credentialsscope, which is granted to
every application by default.
🔐 Scopes
| Scope | Grants |
|---|---|
| read_credentials | Read the merchant public_id / private_id (always included). |
| read_orders | Read orders. |
| write_orders | Create / update orders. |
Request the scopes your integration needs at registration time. The merchant sees these
permissions on the consent screen and must approve them.
🔄 Updating Scopes & Re-Authorization
You can change the scopes your application requests at any time by updating the application.
How it takes effect depends on whether you add or remove scopes.
cURL
curl -X PUT "https://ecartpay.com/api/oauth/applications/<APPLICATION_ID>" \
-H "Authorization: Bearer <DASHBOARD_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"scopes": ["read_orders", "write_orders", "read_customers"]
}'| Change | Effect |
|---|---|
| Removed scopes | Applied immediately to already-connected merchants. No action required from the merchant. |
| Added scopes | Require the merchant to re-authorize (re-consent). Until then, their existing credential keeps the previously granted scopes. |
Why Already-Connected Merchants Still See the Old ScopesA merchant's consent (and the resulting credentials) are snapshotted at authorization
time. Adding scopes to the app does not retroactively grant them to merchants who
connected earlier — they must approve the new permissions once.
Automatic Notification
When you add scopes, Ecart Pay automatically emails every affected merchant (those with
an active credential) a message titled "requests new permissions", including a
re-authorization link that points to your application's OAuth entry point.
How to Apply the New Scopes
| Step | Action |
|---|---|
| 1 | The merchant opens the re-authorization link (from the email) or you send them through GET /oauth again. |
| 2 | Because permissions are pending, Ecart Pay routes the merchant through a short re-consent screen. |
| 3 | On completion, you receive a fresh ?code=... at your redirect_uri, exactly like the first connection. |
| 4 | Exchange the code at POST /api/oauth/token. The response returns the same public_id / private_id and the updated scope. |
| 5 | Generate a new token with those keys — it will carry the new scopes. |
Your Keys Do Not ChangeRe-authorization does not rotate the merchant's
public_id/private_id. You do not
need to request new credentials — only the granted scopes are updated on the same keys.
Tokens Are Scoped at Issue TimeScopes travel inside the token. Tokens issued before the merchant re-authorized keep
the old scopes until they expire. Always generate a new token after the merchant
re-authorizes so it reflects the added permissions.
🏢 Multi-Company Applications
If your partner account manages multiple companies, you can own an OAuth application under
a specific company instead of your personal account. Pass the optional company_id when
creating the application.
cURL
curl -X POST "https://ecartpay.com/api/oauth/applications" \
-H "Authorization: Bearer <DASHBOARD_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Your App",
"redirect_url": "https://yourapp.com/oauth/callback",
"company_id": "665f3b0a9c1d2e4f8a7b6c50",
"scopes": ["read_orders", "write_orders"]
}'| Field | Type | Required | Description |
|---|---|---|---|
| company_id | string | no | Id of a company you own. The application is owned and listed under that company. Omit it (or send null) for a personal application. |
How Ownership Works
- The
company_idmust belong to your account. Otherwise the request fails with
400 The selected company does not exist for this account.- Applications are listed within their owning context: personal applications and each
company's applications are scoped separately.- The OAuth flow, consent, and token exchange work exactly the same regardless of whether
the application is personal or company-owned.
Same Integration, Any Owner
client_id,client_secret, redirect handling, scopes, and the token exchange are
identical for personal and company-owned applications — only the ownership/visibility differs.
🧪 Complete Example
A minimal Node.js backend handling the callback and token exchange:
JavaScript
const express = require('express');
const axios = require('axios');
const app = express();
const BASE_URL = 'https://sandbox.ecartpay.com';
const CLIENT_ID = process.env.ECARTPAY_CLIENT_ID;
const CLIENT_SECRET = process.env.ECARTPAY_CLIENT_SECRET;
const REDIRECT_URI = 'https://yourapp.com/oauth/callback';
// 1. Start the flow: redirect the merchant to Ecart Pay
app.get('/connect', (req, res) => {
const state = crypto.randomUUID();
// persist `state` in the user session for verification
const url = `${BASE_URL}/oauth?client_id=${CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${state}`;
res.redirect(url);
});
// 2. Handle the callback and exchange the code for the merchant credentials
app.get('/oauth/callback', async (req, res) => {
const { code, state } = req.query;
// verify `state` matches the value stored for this user
const { data } = await axios.post(
`${BASE_URL}/api/oauth/token?client_id=${CLIENT_ID}`,
{ grant_type: 'authorization_code', redirect_url: REDIRECT_URI },
{ headers: { Authorization: code, 'x-secret': CLIENT_SECRET } }
);
// The response already contains the merchant API keys.
// Store data.public_id / data.private_id (encrypted) against this merchant.
res.json({
account_id: data.account_id,
public_id: data.public_id,
private_id: data.private_id,
});
});
app.listen(3000);🧪 Testing
Use the Sandbox environment during development:
https://sandbox.ecartpay.com/oauth?client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>
| Step | Action |
|---|---|
| 1 | Create your application against the sandbox base URL. |
| 2 | Use a sandbox merchant account to run the full connect flow. |
| 3 | Confirm you receive ?code=... on your redirect URI and can exchange it. |
| 4 | Confirm GET /api/oauth/credentials returns the merchant keys. |
🚀 Going to Production
| Step | Action |
|---|---|
| 1 | Create (or re-create) your application against https://ecartpay.com. |
| 2 | Whitelist your production redirect_url. |
| 3 | Store the production client_secret securely on your backend. |
| 4 | Switch the entry URL and API calls to the production base URL. |
| 5 | Run the complete flow end-to-end with a real merchant account. |
🧰 Error Reference
| Status / Message | Likely Cause |
|---|---|
403 The redirect_uri is not allowed | redirect_uri does not exactly match a whitelisted URI. |
401 The token is not valid | The code expired (>5 min), was already used, or wrong client_id. |
401 The secret is missing | Missing x-secret header on /api/oauth/token. |
401 The client credentials are not valid | Wrong client_secret for the client_id. |
400 The selected company does not exist for this account | company_id does not belong to your account when creating the application. |
| Merchant still gets a scope/permission error after you added scopes | The merchant has not re-authorized yet — send them through GET /oauth again and re-exchange the code. |
code looks like a URL instead of a token | The merchant arrived through a broken redirect chain — always start the flow at GET /oauth. |
| Merchant not returned / stuck | Verification (KYC level 1) not completed; the merchant must finish before a code is issued. |
🔎 Resources
| Resource | Link |
|---|---|
| Orders API | docs.ecartpay.com/docs/orders |
| API Keys | docs.ecartpay.com/docs/api-keys |
| Webhooks | docs.ecartpay.com/docs/webhooks-in-ecart-pay |
Updated about 6 hours ago