Skip to main content

Understanding API Credentials

Your API credentials are the foundation of secure communication with 88Pay. They consist of two components that work together to authenticate your requests.

API Key

Long-lived secret key used to generate tokensFormat: sk_test_... or sk_live_...

Merchant ID

Your unique identifier in the 88Pay systemFormat: MCH-{COUNTRY}-{ID}
These credentials are highly sensitive. Treat them like passwords—never expose them publicly or commit them to version control.

Obtaining Your Credentials

Step-by-Step Process

1

Create Account

Sign up at dash.88pay.io/signup
  • Provide business information
  • Verify email address
  • Set up password (use a strong, unique password)
2

Complete KYC Verification

Navigate to Account Details in the dashboardRequired documents:
  • Government-issued ID (passport, national ID, driver’s license)
  • Proof of address (utility bill, bank statement < 3 months)
  • Business registration (if applicable)
Document approval typically takes 24-48 hours. You’ll receive an email notification when approved.
3

Access Credentials

Once approved, navigate to Settings → API CredentialsYou’ll see two sets of credentials:
        API Key: sk_test_a1b2c3d4e5f6g7h8i9j0
        Merchant ID: MCH-COL-TEST-29ZTP4
        Base URL: https://api-sandbox.88pay.io
  • Use for development and testing
  • No real money transferred
  • Separate from production credentials
4

Copy & Store Securely

Click the copy icon to copy credentials to clipboardImmediately store them in:
  • Password manager (1Password, LastPass, Bitwarden)
  • Environment variables (.env file)
  • Secret management system (AWS Secrets Manager, HashiCorp Vault)
The API Key is shown only once during creation. If you lose it, you’ll need to regenerate a new one.

Credential Formats

API Key Structure

# Sandbox
sk_test_{32_character_random_string}

# Production
sk_live_{32_character_random_string}
Characteristics:
  • Always starts with sk_test_ (sandbox) or sk_live_ (production)
  • Followed by 32 alphanumeric characters
  • Case-sensitive
  • No expiration (unless manually rotated)

Merchant ID Structure

MCH-{COUNTRY}-{UNIQUE_ID}

# Examples:
MCH-COL-29ZTP4        # Colombia
MCH-MEX-8K2PQ1        # Mexico
MCH-BRA-7N4WX9        # Brazil
MCH-COL-TEST-29ZTP4   # Sandbox (includes "TEST")
Components:
  • MCH: Merchant prefix (constant)
  • {COUNTRY}: 3-letter country code (COL, MEX, BRA, etc.)
  • {UNIQUE_ID}: Random identifier (6 characters)
  • Sandbox includes -TEST- segment

Storing Credentials Securely

Create .env file:
    # .env
    EIGHTY_EIGHT_PAY_API_KEY=sk_test_a1b2c3d4e5f6g7h8i9j0
    EIGHTY_EIGHT_PAY_MERCHANT_ID=MCH-COL-TEST-29ZTP4
    EIGHTY_EIGHT_PAY_BASE_URL=https://api-sandbox.88pay.io
Load with dotenv:
    // Load at app startup
    require('dotenv').config();
    
    const apiKey = process.env.EIGHTY_EIGHT_PAY_API_KEY;
    const merchantId = process.env.EIGHTY_EIGHT_PAY_MERCHANT_ID;
    const baseUrl = process.env.EIGHTY_EIGHT_PAY_BASE_URL;
Add to .gitignore:
    .env
    .env.*
    !.env.example

Cloud Secret Managers

    # Store secret
    aws secretsmanager create-secret \
      --name 88pay/api-credentials \
      --secret-string '{
        "api_key": "sk_live_...",
        "merchant_id": "MCH-COL-..."
      }'
    
    # Retrieve in application
    aws secretsmanager get-secret-value \
      --secret-id 88pay/api-credentials
Node.js SDK:
    const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
    
    const client = new SecretsManagerClient({ region: "us-east-1" });
    const response = await client.send(
      new GetSecretValueCommand({ SecretId: "88pay/api-credentials" })
    );
    
    const credentials = JSON.parse(response.SecretString);
    # Store secret
    echo -n "sk_live_..." | gcloud secrets create 88pay-api-key --data-file=-
    echo -n "MCH-COL-..." | gcloud secrets create 88pay-merchant-id --data-file=-
    
    # Retrieve in application
    gcloud secrets versions access latest --secret="88pay-api-key"
    # Store secret
    vault kv put secret/88pay \
      api_key="sk_live_..." \
      merchant_id="MCH-COL-..."
    
    # Retrieve in application
    vault kv get -field=api_key secret/88pay
    # Store secret
    az keyvault secret set \
      --vault-name my-vault \
      --name 88pay-api-key \
      --value "sk_live_..."
    
    # Retrieve in application
    az keyvault secret show \
      --vault-name my-vault \
      --name 88pay-api-key

Security Best Practices

❌ Don’t do this:
    // Hardcoded credentials (EXPOSED!)
    const API_KEY = 'sk_live_abc123...';
    const MERCHANT_ID = 'MCH-COL-29ZTP4';
✅ Do this instead:
    // Load from environment variables
    const API_KEY = process.env.EIGHTY_EIGHT_PAY_API_KEY;
    const MERCHANT_ID = process.env.EIGHTY_EIGHT_PAY_MERCHANT_ID;
Hardcoded credentials can be:
  • Committed to Git repositories
  • Exposed in error logs
  • Found in browser DevTools
  • Leaked through code screenshots

Additional Security Measures

For production environments:
  1. Navigate to Settings → Security in dashboard
  2. Add your server IPs (IPv4 and IPv6)
  3. API will reject requests from non-whitelisted IPs
Example:
    Whitelisted IPs:
    - 203.0.113.10 (Production Server 1)
    - 203.0.113.11 (Production Server 2)
    - 2001:db8::1 (IPv6 Server)
Update IP whitelist when scaling infrastructure or changing hosting providers.
Set up alerts for:
  • Unexpected spike in API calls
  • Failed authentication attempts (401/403)
  • Requests from unknown IPs
  • Unusual transaction patterns
Integration examples:
    const Sentry = require("@sentry/node");
    
    // Track failed auth attempts
    if (response.status === 401) {
      Sentry.captureMessage('88Pay Auth Failed', {
        level: 'warning',
        tags: { service: '88pay' }
      });
    }
Log these fields (but NOT credentials):
    {
      timestamp: '2025-01-17T14:30:00Z',
      endpoint: '/api/transactions/charges',
      method: 'POST',
      status_code: 200,
      response_time_ms: 342,
      merchant_id: 'MCH-COL-29ZTP4',  // OK to log
      transaction_ref: 'IP9BD7CJES6',  // OK to log
      // api_key: '...'  ⚠️ NEVER LOG THIS!
      // access_token: '...'  ⚠️ NEVER LOG THIS!
    }
Never log:
  • API Keys
  • Access Tokens
  • Customer card numbers
  • CVV codes
  • Full bank account numbers
All communications must use HTTPS:
  • ✅ API requests: https://api.88pay.io
  • ✅ Webhook URLs: https://yoursite.com/webhook
  • ✅ Return URLs: https://yoursite.com/payment-success
  • ❌ HTTP requests will be rejected
Verify SSL certificates:
    # Check certificate validity
    openssl s_client -connect api.88pay.io:443 -servername api.88pay.io

Rotating Credentials

When to Rotate

Proactive security measureSet a recurring calendar reminder to rotate keys quarterly. This limits exposure if a key is compromised without your knowledge.
Immediate rotation required if:
  • Key accidentally committed to Git
  • Shared with unauthorized person
  • Found in logs or error messages
  • Employee with access leaves company
  • Suspicious API activity detected
After any security audit or penetration test that flags credential management issues.

Rotation Process

1

Generate New Key

In the dashboard, navigate to Settings → API CredentialsClick “Regenerate API Key”
This will generate a new key. The old key will remain active for 24 hours.
2

Update Application

Update environment variables in all environments:
    # Development
    EIGHTY_EIGHT_PAY_API_KEY=sk_live_NEW_KEY_HERE
    
    # Staging
    EIGHTY_EIGHT_PAY_API_KEY=sk_live_NEW_KEY_HERE
    
    # Production (deploy carefully!)
    EIGHTY_EIGHT_PAY_API_KEY=sk_live_NEW_KEY_HERE
3

Deploy Changes

Deploy updated configuration to all serversZero-downtime deployment:
  1. Both old and new keys work during transition
  2. Rolling deployment ensures no downtime
  3. Old key deactivates after 24 hours
4

Verify & Deactivate

Monitor for any errors using old keyAfter 24 hours, old key is automatically deactivatedIf issues arise, you can manually deactivate new key and revert

Testing Your Credentials

Quick Verification

Test that your credentials work:
# Test authentication
curl -X POST "https://api-sandbox.88pay.io/api/auth/token" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "x-merchant-id: YOUR_MERCHANT_ID"

# Expected response:
# { "status": "Success", "code": 200, "data": { "access_token": "...", ... } }

Common Errors

    { "code": 401, "message": "Invalid API key or merchant ID" }
Causes:
  • Typo in API Key or Merchant ID
  • Using sandbox key with production endpoint (or vice versa)
  • Extra whitespace in credentials
  • Key has been rotated/deactivated
Fix:
  1. Copy credentials directly from dashboard
  2. Verify environment matches (sandbox vs production)
  3. Check for hidden characters: apiKey.trim()
    { "code": 403, "message": "Access denied" }
Causes:
  • Account not yet approved
  • Account suspended
  • IP not whitelisted (if enabled)
Fix: Contact support@88pay.io

Credential Checklist

Before moving to the next guide, verify:
  • Account created and email verified
  • KYC documents uploaded and approved
  • Sandbox credentials copied from dashboard
  • Credentials stored in environment variables (not hardcoded)
  • .env added to .gitignore
  • Credentials tested successfully
  • Production credentials obtained (when ready for go-live)

Next Steps