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:

RequirementDescription
Ecart Pay AccountActive account that will own the OAuth application (the partner / platform account).
Dashboard TokenAn authorization token with the write_oauth_applications scope to create the application.
HTTPS RedirectA redirect URI served over HTTPS where Ecart Pay returns the authorization code.
BackendA 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.com

Use the sandbox while developing. Switch to production only when you are ready to go live.


🔑 How the Flow Works

StepDescription
1You create an OAuth application and receive a client_id and client_secret.
2You redirect the merchant to GET /oauth with your client_id and redirect_uri.
3The merchant signs in, completes verification (KYC levels 0 → 1) if needed, and grants consent.
4Ecart Pay redirects back to your redirect_uri with a single-use ?code=....
5Your backend exchanges the code (+ client_secret) and receives the merchant account_id, public_id, and private_id directly.
👍

One-Time Verification

A 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 Secret

The client_secret is returned only once. Store it securely on your backend.
You can rotate it later with POST /api/oauth/applications/:id/secret.

Body Parameters

ParameterTypeRequiredDescription
namestringyesApplication name shown on the consent screen.
redirect_urlstringyesHTTPS callback URL. Must be matched exactly on redirect.
descriptionstringnoShort description shown on the consent screen.
logo_urlstringnoLogo shown on the consent screen.
company_idstringnoOwn the application under one of your companies instead of your personal account. See Multi-Company Applications.
scopesarraynoRequested scopes (see Scopes). read_credentials is always added.
onboarding.headlinestringnoCustom consent screen title.
onboarding.permissions_summaryarraynoBullet 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

ParameterTypeRequiredDescription
client_idstringyesYour application's client id.
redirect_uristringyesMust match a whitelisted redirect URI exactly.
statestringrecommendedOpaque value echoed back to you; use it for CSRF protection.
📘

What the Merchant Sees

Ecart 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 state matches the value you sent.
  • The code is 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 Exchange

The token exchange returns the merchant account_id, public_id, and private_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 Securely

The private_id is a secret. Store it encrypted on your backend, just like your
client_secret, and never expose it in the browser.

Request Reference

LocationFieldDescription
Queryclient_idYour application's client id.
HeaderAuthorizationThe authorization code.
Headerx-secretYour client_secret.
Bodygrant_typeauthorization_code.
Bodyredirect_urlThe same redirect URI used in the flow.
📘

Scope Required

Returning the credentials requires the read_credentials scope, which is granted to
every application by default.


🔐 Scopes

ScopeGrants
read_credentialsRead the merchant public_id / private_id (always included).
read_ordersRead orders.
write_ordersCreate / 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"]
  }'
ChangeEffect
Removed scopesApplied immediately to already-connected merchants. No action required from the merchant.
Added scopesRequire 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 Scopes

A 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

StepAction
1The merchant opens the re-authorization link (from the email) or you send them through GET /oauth again.
2Because permissions are pending, Ecart Pay routes the merchant through a short re-consent screen.
3On completion, you receive a fresh ?code=... at your redirect_uri, exactly like the first connection.
4Exchange the code at POST /api/oauth/token. The response returns the same public_id / private_id and the updated scope.
5Generate a new token with those keys — it will carry the new scopes.
👍

Your Keys Do Not Change

Re-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 Time

Scopes 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"]
  }'
FieldTypeRequiredDescription
company_idstringnoId 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_id must 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>
StepAction
1Create your application against the sandbox base URL.
2Use a sandbox merchant account to run the full connect flow.
3Confirm you receive ?code=... on your redirect URI and can exchange it.
4Confirm GET /api/oauth/credentials returns the merchant keys.

🚀 Going to Production

StepAction
1Create (or re-create) your application against https://ecartpay.com.
2Whitelist your production redirect_url.
3Store the production client_secret securely on your backend.
4Switch the entry URL and API calls to the production base URL.
5Run the complete flow end-to-end with a real merchant account.

🧰 Error Reference

Status / MessageLikely Cause
403 The redirect_uri is not allowedredirect_uri does not exactly match a whitelisted URI.
401 The token is not validThe code expired (>5 min), was already used, or wrong client_id.
401 The secret is missingMissing x-secret header on /api/oauth/token.
401 The client credentials are not validWrong client_secret for the client_id.
400 The selected company does not exist for this accountcompany_id does not belong to your account when creating the application.
Merchant still gets a scope/permission error after you added scopesThe 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 tokenThe merchant arrived through a broken redirect chain — always start the flow at GET /oauth.
Merchant not returned / stuckVerification (KYC level 1) not completed; the merchant must finish before a code is issued.

🔎 Resources


Did this page help you?