Skip to main content

Authorization

Receive authorization by asking for the required permissions.

info

This is a OAuth 2.0 compliant Authorization Code flow implementation with PKCE.

info

Implement this authentication and authorization flow by leveraging widely-available OAuth 2.0 client libraries (e.g., OAuthLib for Python, Spring Security OAuth for Java, or MSAL for .NET).

App Authorization

Step by step

Create an App

First you need to create an app on app.depay.com.

Create App

Go to Apps > New App and provide all the information required.

App Details

App ID & Secret

Copy your App ID and your App Secret into your app.

App Dashboard

danger

Treat your App Secret like a password—store it securely on your back-end, never embed or expose it in any front-end code, and use it only for server-to-server token exchanges.

Enable User Authorization

Right after creating your app or after navigating your app on app.depay.com Apps > Your App click "Enable" within the "User Authorization" section.

Enable User Authorization

Required Permissions

Now select the permissions your app requires.

See: List of all app permissions and their detailed descriptions.

Redirect URL

Now set the redirect URL where users should be send to after they have granted your app permissions.

Authorization URL

Make sure you copy the "Authorization URL".

This is the URL you need to send users to in order to start a user authorization flow.

Initiate Authorization Request

Generate and store a high-entropy code_verifier (32+ random bytes, URL-safe):

code_verifier         = BASE64URL( RANDOM_BYTES(32) )        # 43–128 characters
code_challenge_method = S256
code_challenge = BASE64URL( SHA256(code_verifier) )
state = BASE64URL( RANDOM_BYTES(16) ) # 22 characters

Redirect the user’s browser to DePay’s authorization endpoint:

GET https://app.depay.com/authorize
?response_type=code
&client_id=<YOUR_APP_ID>
&code_challenge_method=S256
&code_challenge=${code_challenge}
&state=${state}
caution

To prevent open‐redirect attacks, all users will be redirected to the pre‐registered redirect URI configured in your app dashboard on app.depay.com.

Handle the Redirect

After the user approves or denies, DePay will redirect to your (on app.depay.com) pre-configured redirect url with:

  • code — the authorization code (on success)

  • state — the same value you sent

Example callback URL (on success):

https://yourapp.com/callback
?code=SplxlOBeZQQYbYS6WxSbIA
&state=xyzABC123

Server-side must:

  • Verify state matches the one you stored.

  • Retrieve the original code_verifier for this attempt.

Exchange Authorization Code for Access Token

danger

Ensure all token exchanges occur via your backend directly to DePay APIs only.

From your server back-end only, make a POST request to the oauth/token endpoint:

### POST https://api.depay.com/oauth/token

+ Request (application/json)

{
"grant_type": "authorization_code",
"client_id": "<YOUR_APP_ID>",
"client_secret": "<YOUR_APP_SECRET>",
"code": "<AUTHORIZATION_CODE>",
"code_verifier": "<ORIGINAL_CODE_VERIFIER>"
}

+ Response 200 (application/json)

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": "2022-11-10T14:30:00.436Z",
"refresh_token": "def50200a45f…",
"scope": "payments.read integrations.read"
}
info

A given authorization_code can be exchanged only once.

info

Store access_token, refresh_token and store its expiry (expires_at).

Refresh an Access Token

When your stored access_token expires or you receive a response with status code 401:

+ Response 401 (application/json)

+ Headers

WWW-Authenticate: Bearer realm="api.depay.com", error="invalid_token"

+ Body

{
"error": "invalid_token",
"error_description": "The refresh token is invalid, expired, or has already been used.",
}

Refresh the access_token server-side:

### POST https://api.depay.com/oauth/token

+ Request (application/json)

{
"grant_type": "refresh_token",
"client_id": "<YOUR_APP_ID>",
"client_secret": "<YOUR_APP_SECRET>",
"refresh_token": "<STORED_REFRESH_TOKEN>"
}

+ Response 200 (application/json)

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": "2022-11-10T14:30:00.436Z",
"refresh_token": "ghi703d2b…",
"scope": "payments.read integrations.read"
}
info

A given refresh_token can be exchanged only once. If you try to reuse it you’ll get an invalid_grant/invalid_token error and must re-authorize the user.

info

Update your storage of access_token, refresh_token and store its expiry (expires_at).

Re-authorization Required

If at any point your access or refresh token is invalid, expired, or revoked, your app must prompt the user to re-authorize. Below are common responses that indicate a full re-authorization is needed.

Invalid or Expired Refresh Token

When you attempt to refresh with an invalid or one-time-use refresh token:

+ Response 400 (application/json)

+ Body

{
"error": "invalid_grant",
"error_description": "The refresh token is invalid, expired, or has already been used."
}

Invalid or Expired Access Token

If you use an access token that the server no longer recognizes:

+ Response 401 (application/json)

+ Headers

WWW-Authenticate: Bearer realm="api.depay.com", error="invalid_token"

+ Body

{
"error": "invalid_token",
"error_description": "The access token is invalid or has expired."
}

Insufficient Scope

If your access token lacks the required permissions for an endpoint:

+ Response 403 (application/json)

+ Headers

WWW-Authenticate: Bearer realm="api.depay.com", error="insufficient_scope"

+ Body

{
"error": "insufficient_scope",
"error_description": "The access token does not have the required scope: payments.read"
}

Testing Integration

Because DePay enforces exact, pre-registered redirect URIs, you should create a separate app configuration for each environment (e.g. development, staging, production).

This ensures your redirect URIs match exactly and prevents authorization failures.