---
title: OAuth2 Integration Guide
audience: public
summary: Authenticate with the WeeConnectPay API using OAuth2 client credentials — environments, token requests, JWT lifetime, and error handling for third-party integrations.
---

# WeeConnectPay API - OAuth2 Integration Guide

This guide explains how to authenticate with the WeeConnectPay API using OAuth2 client credentials.

> **See also:** The [Integration Architecture Guide](INTEGRATION_ARCHITECTURE_GUIDE.md) explains what your token represents, how Clover entities relate, and how to design integrations that handle real-world disruptions gracefully.
>
> **New:** The [Device Authorization Guide](DEVICE_AUTHORIZATION_GUIDE.md) explains how plugins can obtain credentials automatically using a one-time code — no manual copy-paste required.

## Environments

| Environment | Dashboard URL | API Base URL |
|-------------|---------------|--------------|
| **Sandbox** | `https://dashboard.sandbox.weeconnectpay.com` | `https://apidev.weeconnectpay.com` |
| **Staging** | `https://dashboard.staging.weeconnectpay.com` | `https://apidev.weeconnectpay.com` |
| **Production** | `https://dashboard.weeconnectpay.com` | `https://api.weeconnectpay.com` |

> **Important:** Credentials are environment-specific. Sandbox credentials only work with the sandbox dashboard, staging credentials with staging, and production credentials with production. Always test your integration in a non-production environment before going live.
>
> **Sandbox vs Staging:** The sandbox environment is for merchants and integrators who want to test the integration — access is granted by employee invite to a pre-configured sandbox merchant. The staging environment is for developers actively building integrations and offers a stable environment unaffected by other testers. Both share the same API base URL. For day-to-day development, use **staging**; for demonstrating or evaluating the product, use **sandbox**.

---

## Quick Start

### 1. Obtain Client Credentials

1. Log in to the WeeConnectPay Dashboard for your target environment
2. Navigate to the API Clients section
3. Click **Create New Client**
4. Store your `client_id` and `client_secret` securely

> **Important:** The `client_secret` is only shown once at creation. Store it immediately in a secure location.

### 2. Request an Access Token

Exchange your client credentials for an access token:

```bash
curl -X POST https://apidev.weeconnectpay.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'
```

**Response:**
```json
{
  "token_type": "Bearer",
  "expires_in": 31536000,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."
}
```

### 3. Use the Access Token

Include the token in the `Authorization` header for all API requests:

```bash
curl -X GET https://apidev.weeconnectpay.com/v1/your-endpoint \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

---

## Authentication Flow

### Client Credentials Grant

The WeeConnectPay API uses the OAuth2 **Client Credentials** grant type. This is ideal for server-to-server integrations.

```
┌─────────────────┐                              ┌─────────────────┐
│                 │  1. POST /oauth/token        │                 │
│  Your Server    │  (client_id, client_secret)  │  WeeConnectPay  │
│                 │ ───────────────────────────> │  API            │
│                 │                              │                 │
│                 │  2. Access Token             │                 │
│                 │ <─────────────────────────── │                 │
│                 │                              │                 │
│                 │  3. API Request              │                 │
│                 │  (Authorization: Bearer)     │                 │
│                 │ ───────────────────────────> │                 │
│                 │                              │                 │
│                 │  4. API Response             │                 │
│                 │ <─────────────────────────── │                 │
└─────────────────┘                              └─────────────────┘
```

### Token Request

**Endpoint:** `POST /oauth/token`

**Headers:**
| Header | Value |
|--------|-------|
| `Content-Type` | `application/json` |

**Body Parameters:**
| Parameter | Required | Description |
|-----------|----------|-------------|
| `grant_type` | Yes | Must be `client_credentials` |
| `client_id` | Yes | Your OAuth client ID (UUID format) |
| `client_secret` | Yes | Your OAuth client secret |

---

## Token Management

### Token Expiration

Access tokens are valid for **1 year** (31,536,000 seconds) from the time of issuance.

The `expires_in` field in the token response indicates the token lifetime in seconds.

### Obtaining a New Token

When your token expires (or is close to expiring), simply request a new token using your client credentials:

```bash
curl -X POST https://apidev.weeconnectpay.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'
```

> **Note:** The client credentials grant does not use refresh tokens. Since you have your credentials, you can request a new access token at any time.

### Revoking Access

To revoke access, delete or regenerate the OAuth client in the WeeConnectPay Dashboard.

---

## Code Examples

### JavaScript (Node.js)

```javascript
const axios = require('axios');

const API_BASE_URL = 'https://apidev.weeconnectpay.com';
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';

async function getAccessToken() {
  const response = await axios.post(`${API_BASE_URL}/oauth/token`, {
    grant_type: 'client_credentials',
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET
  });

  return response.data.access_token;
}

async function makeApiRequest(endpoint) {
  const token = await getAccessToken();

  const response = await axios.get(`${API_BASE_URL}${endpoint}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  return response.data;
}

// Usage
makeApiRequest('/v1/your-endpoint')
  .then(data => console.log(data))
  .catch(error => console.error(error));
```

### PHP

```php
<?php

$apiBaseUrl = 'https://apidev.weeconnectpay.com';
$clientId = 'your-client-id';
$clientSecret = 'your-client-secret';

function getAccessToken($apiBaseUrl, $clientId, $clientSecret) {
    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_URL => "{$apiBaseUrl}/oauth/token",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode([
            'grant_type' => 'client_credentials',
            'client_id' => $clientId,
            'client_secret' => $clientSecret
        ])
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($response, true);
    return $data['access_token'];
}

function makeApiRequest($apiBaseUrl, $accessToken, $endpoint) {
    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_URL => "{$apiBaseUrl}{$endpoint}",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            "Authorization: Bearer {$accessToken}",
            'Content-Type: application/json'
        ]
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Usage
$token = getAccessToken($apiBaseUrl, $clientId, $clientSecret);
$data = makeApiRequest($apiBaseUrl, $token, '/v1/your-endpoint');
print_r($data);
```

### Python

```python
import requests

API_BASE_URL = 'https://apidev.weeconnectpay.com'
CLIENT_ID = 'your-client-id'
CLIENT_SECRET = 'your-client-secret'

def get_access_token():
    response = requests.post(
        f'{API_BASE_URL}/oauth/token',
        json={
            'grant_type': 'client_credentials',
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET
        }
    )
    response.raise_for_status()
    return response.json()['access_token']

def make_api_request(endpoint):
    token = get_access_token()

    response = requests.get(
        f'{API_BASE_URL}{endpoint}',
        headers={
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
    )
    response.raise_for_status()
    return response.json()

# Usage
data = make_api_request('/v1/your-endpoint')
print(data)
```

---

## Using Postman

1. Create a new request in Postman
2. Go to the **Authorization** tab
3. Select **OAuth 2.0** as the type
4. Configure:
   - **Grant Type:** Client Credentials
   - **Access Token URL:** `https://apidev.weeconnectpay.com/oauth/token`
   - **Client ID:** Your client ID
   - **Client Secret:** Your client secret
5. Click **Get New Access Token**
6. Use the token for your API requests

---

## Error Handling

### Common Error Responses

**Invalid Credentials (401)**
```json
{
  "error": "invalid_client",
  "error_description": "Client authentication failed",
  "message": "Client authentication failed"
}
```

**Invalid Grant Type (400)**
```json
{
  "error": "unsupported_grant_type",
  "error_description": "The authorization grant type is not supported by the authorization server.",
  "message": "The authorization grant type is not supported by the authorization server."
}
```

**Expired or Invalid Token (401)**
```json
{
  "message": "Unauthenticated."
}
```

**Rate Limited (429)**
```json
{
  "message": "Too Many Requests"
}
```

### Handling Token Expiration

When you receive a `401 Unauthenticated` response, your token may have expired. Request a new token and retry:

```javascript
async function makeRequestWithRetry(endpoint, retried = false) {
  try {
    return await makeApiRequest(endpoint);
  } catch (error) {
    if (error.response?.status === 401 && !retried) {
      // Token expired, get a new one and retry
      cachedToken = null;
      return makeRequestWithRetry(endpoint, true);
    }
    throw error;
  }
}
```

---

## Rate Limiting

The API enforces rate limits to ensure fair usage:

- **60 requests per minute** per token

When rate limited, you'll receive a `429 Too Many Requests` response. Implement exponential backoff in your retry logic.

---

## Security Best Practices

1. **Never expose credentials in client-side code** - Only use client credentials in server-side applications

2. **Store credentials securely** - Use environment variables or a secrets manager, never commit credentials to version control

3. **Use HTTPS only** - All API requests must use HTTPS

4. **Rotate credentials periodically** - Generate new client credentials from the dashboard and update your application

5. **Monitor for unauthorized access** - Review API usage in the dashboard regularly

6. **Use separate credentials per environment** - Never use staging credentials in production or vice versa

---

## Support

If you encounter issues with authentication:

1. Verify your `client_id` and `client_secret` are correct
2. Ensure you're using credentials for the correct environment (staging vs. production)
3. Check that your credentials haven't been revoked in the dashboard
4. Verify the `grant_type` is set to `client_credentials`

5. See the [PrestaShop Integration Guide](PRESTASHOP_INTEGRATION_GUIDE.md) for a complete PrestaShop integration example
6. See the [Zoho Catalyst Integration Guide](ZOHO_CATALYST_INTEGRATION_GUIDE.md) for a complete Zoho integration example

For additional support, contact the WeeConnectPay team.