Skip to main content

Authentication

Qoyod's v2 API accepts two authentication methods. Both work on all three endpoints covered in this guide. Use whichever fits your integration architecture.

API Key Authentication

All API requests require authentication using an API key. The API key must be included in the request header.

Generating Your API Key

  • Log in to your Qoyod account at https://www.qoyod.com.
  • Navigate to Settings → General Settings.
  • Click Generate New Key.
  • Click Save to confirm.
  • Important: Copy and securely store your API key immediately. For security reasons, you won't be able to view it again.

Using Your API Key

Pass your API key in a custom HTTP header on every request:

API-KEY: qyd_live_a7f3c92e1b4d8056e3a1c09f72b4d835
curl -X GET "https://api.qoyod.com/v1/accounts" \
-H "API-KEY: qyd_live_a7f3c92e1b4d8056e3a1c09f72b4d835" \
-H "Content-Type: application/json"
info

API key requests are never rejected for scope reasons — once the key is valid, access is granted.

OAuth Authentication

info

When to use OAuth: if your integration acts on behalf of a specific Qoyod user, or if your platform needs to request access without embedding a long-lived API key.

Pass the token in the standard Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Supported Grant Flows

FlowUse Case
Authorization CodeServer-side web applications — recommended for most integrations
Client CredentialsMachine-to-machine integrations with no user context

Available Scopes

Request only the scopes your integration needs. Qoyod's admin may restrict the scopes available to your application.

Contact your tenant admin or Qoyod support for the full list of available scopes and what resources they grant access to.


Authorization Code Flow

Use this flow when your integration acts on behalf of a Qoyod user.

Flow Overview


Step 1 — Redirect the User to Qoyod's Authorization Endpoint

Send the user's browser to:

GET https://app.qoyod.com/oauth/authorize

Required parameters:

ParameterDescription
client_idYour application's Client ID
redirect_uriThe URI Qoyod will redirect back to — must exactly match the one registered
response_typeMust be code
scopeSpace-separated list of scopes (e.g., read write)
tenantYour organization's Qoyod tenant identifier (provided by Qoyod's admin/support)

Example:

https://app.qoyod.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/oauth/callback
&response_type=code
&scope=read
&tenant=your-tenant-identifier

The user will be prompted to sign in (if not already) and approve the requested scopes.


Step 2 — Handle the Callback

After the user approves, Qoyod redirects to your redirect_uri with a short-lived authorization code:

https://yourapp.com/oauth/callback?code=AUTHORIZATION_CODE

If the user denies access:

https://yourapp.com/oauth/callback?error=access_denied

Important: The authorization code is single-use and expires in 10 minutes. Exchange it for an access token immediately.


Step 3 — Exchange the Code for an Access Token

POST https://app.qoyod.com/oauth/token
Content-Type: application/x-www-form-urlencoded

Request body:

ParameterValue
grant_typeauthorization_code
codeThe authorization code from Step 2
client_idYour application's Client ID
client_secretYour application's Client Secret
redirect_uriSame URI used in Step 1
tenantYour organization's Qoyod tenant identifier (provided by Qoyod's admin/support)

Example (curl):

curl -X POST https://app.qoyod.com/oauth/token \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=https://yourapp.com/oauth/callback" \
-d "tenant=your-tenant-identifier"

Successful response:

{
"access_token": "eyJhbGciOiJIUzUxMiJ9...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "abc123...",
"scope": "read",
"created_at": 1700000000
}

Client Credentials Flow

Use this flow for server-to-server integrations that do not act on behalf of a specific user. Your application must be registered as a confidential application by your Qoyod admin.

This flow requires a confidential application. Non-confidential applications are not permitted to use client credentials. Contact your tenant admin to verify your application type.

Flow Overview

Request

POST https://app.qoyod.com/oauth/token
Content-Type: application/x-www-form-urlencoded
ParameterValue
grant_typeclient_credentials
client_idYour application's Client ID
client_secretYour application's Client Secret
scopeSpace-separated list of scopes
tenantYour organization's Qoyod tenant identifier (provided by Qoyod's admin/support)

Example (curl):

curl -X POST https://app.qoyod.com/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=read" \
-d "tenant=your-tenant-identifier"

Successful response:

{
"access_token": "eyJhbGciOiJIUzUxMiJ9...",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "read",
"created_at": 1700000000
}

Using the Access Token

Include the access token as a Bearer token in the Authorization header of every API request:

GET https://app.qoyod.com/api/2.0/invoices
Authorization: Bearer YOUR_ACCESS_TOKEN

Access tokens expire after 2 hours. Check the expires_in field in the token response to know when to refresh.


Refreshing an Access Token

When an access token expires, use your refresh token to obtain a new one without requiring the user to re-authorize. Refresh tokens are issued during the Authorization Code flow.

Request

POST https://app.qoyod.com/oauth/token
Content-Type: application/x-www-form-urlencoded
ParameterValue
grant_typerefresh_token
refresh_tokenYour current refresh token
client_idYour application's Client ID
client_secretYour application's Client Secret

Example (curl):

curl -X POST https://app.qoyod.com/oauth/token \
-d "grant_type=refresh_token" \
-d "refresh_token=YOUR_REFRESH_TOKEN" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"

Successful response:

{
"access_token": "eyJhbGciOiJIUzUxMiJ9...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "xyz789...",
"scope": "read",
"created_at": 1700003600
}

Important: Each refresh issues a new refresh token. Discard the old one and store the new one immediately.


Error Reference

HTTP StatusErrorMeaning
401 Unauthorizedinvalid_clientWrong client_id or client_secret
401 Unauthorizedinvalid_grantAuthorization code is expired, already used, or mismatched redirect_uri
401 UnauthorizedInvalid refresh tokenRefresh token is invalid or revoked
401 UnauthorizedInvalid grant typeAttempted client_credentials with a non-confidential app
403 ForbiddenAccess deniedYour application is not authorized for this tenant
401 Unauthorizedaccess_deniedUser denied the authorization request

Complete Integration Checklist

  • Tenant admin has created an OAuth application and shared credentials with you
  • client_id and client_secret are stored securely (not in source code or client-side assets)
  • redirect_uri is registered exactly as it will be used in requests
  • Authorization codes are exchanged immediately upon receipt
  • Access tokens are sent via Authorization: Bearer header over HTTPS only
  • Refresh tokens are stored securely and updated on every refresh
  • Your application handles 401 responses and triggers a token refresh or re-authorization
  • You have a process to contact [email protected] in case of credential compromise

Support

For integration assistance or to report a security incident (credential leakage, unauthorized access), contact:

Qoyod Support: [email protected]