Skip to content

Error Handling ​

Complete guide to understanding and handling YeboLink API errors effectively.

Error Response Format ​

All error responses follow this consistent structure:

json
{
  "success": false,
  "error": "Human-readable error message"
}

HTTP Status Codes ​

400 Bad Request ​

Invalid request parameters or validation errors.

Common Causes:

  • Missing required fields
  • Invalid phone number format
  • Invalid email format
  • Invalid date format
  • Invalid enum values

Example:

json
{
  "success": false,
  "error": "Phone number must be in E.164 format (e.g., +26878422613)"
}
bash
curl -X POST https://api.yebolink.com/api/v1/messages/send \
  -H "X-API-Key: ybk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "invalid_phone",
    "channel": "sms",
    "content": { "text": "Hello" }
  }'

How to Fix:

  • Validate phone numbers using E.164 format: +[country_code][number]
  • Check required fields in request body
  • Ensure enum values match accepted values
  • Use proper date formats (ISO 8601)

401 Unauthorized ​

Authentication failed or missing credentials.

Common Causes:

  • Missing API key or JWT token
  • Invalid API key
  • Expired JWT token
  • Deactivated API key

Example:

json
{
  "success": false,
  "error": "Invalid API key"
}
bash
curl -X POST https://api.yebolink.com/api/v1/messages/send \
  -H "X-API-Key: ybk_invalid_key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+26878422613",
    "channel": "sms",
    "content": { "text": "Hello" }
  }'

How to Fix:

  • Verify your API key is correct
  • Check that the API key hasn't been deactivated
  • For JWT: Login again to get a fresh token
  • Ensure you're using the correct authentication method for the endpoint

402 Payment Required ​

Insufficient credits to complete the operation.

Common Causes:

  • Credit balance is zero or too low
  • Attempted bulk send without enough credits

Example:

json
{
  "success": false,
  "error": "Insufficient credits. You need 100 credits but have 50."
}
javascript
try {
  const response = await fetch('https://api.yebolink.com/api/v1/messages/bulk', {
    method: 'POST',
    headers: {
      'X-API-Key': 'ybk_your_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      channel: 'sms',
      content: { text: 'Hello {{name}}' },
      recipients: [...100_recipients]
    })
  });

  if (response.status === 402) {
    // Redirect user to purchase credits
    window.location.href = '/billing';
  }
} catch (error) {
  console.error(error);
}

How to Fix:

  • Purchase more credits via the dashboard
  • Check your credit balance before sending
  • Implement credit balance checks in your application

403 Forbidden ​

Valid authentication but insufficient permissions.

Common Causes:

  • API key doesn't have required scopes
  • Trying to access another workspace's resources

Example:

json
{
  "success": false,
  "error": "API key does not have required scope: manage_webhooks"
}

How to Fix:

  • Create a new API key with correct scopes
  • Verify you're accessing resources from your own workspace

404 Not Found ​

The requested resource doesn't exist.

Common Causes:

  • Invalid message ID
  • Message doesn't belong to your workspace
  • Webhook, contact, or API key not found

Example:

json
{
  "success": false,
  "error": "Message not found"
}
python
import requests

response = requests.get(
    'https://api.yebolink.com/api/v1/messages/invalid-uuid',
    headers={'X-API-Key': 'ybk_your_key'}
)

if response.status_code == 404:
    print("Message not found")
elif response.ok:
    data = response.json()
    print(data)

How to Fix:

  • Verify the resource ID is correct
  • Ensure the resource belongs to your workspace
  • Check that the resource hasn't been deleted

429 Too Many Requests ​

Rate limit exceeded.

Common Causes:

  • Sending too many requests too quickly
  • Exceeding bulk send rate limits
  • Too many failed authentication attempts

Example:

json
{
  "success": false,
  "error": "Rate limit exceeded. Try again in 30 seconds."
}
javascript
async function sendWithRetry(messageData, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch('https://api.yebolink.com/api/v1/messages/send', {
        method: 'POST',
        headers: {
          'X-API-Key': process.env.YEBOLINK_API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(messageData)
      });

      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || '30';
        const delay = parseInt(retryAfter) * 1000;
        console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
}

Rate Limits:

Endpoint TypeLimit
API Key endpoints100 requests/minute
Bulk messaging10 requests/minute
Auth endpoints5 attempts/15 minutes

How to Fix:

  • Implement exponential backoff
  • Use the Retry-After header value
  • Batch requests where possible
  • Use bulk endpoints instead of multiple single requests

500 Internal Server Error ​

Server-side error occurred.

Common Causes:

  • Temporary service disruption
  • Database connection issues
  • Third-party provider errors (Twilio, Stripe, etc.)

Example:

json
{
  "success": false,
  "error": "Internal server error. Please try again later."
}

How to Fix:

  • Retry the request after a short delay
  • If the error persists, contact support
  • Check the status page for known issues

Error Codes Reference ​

Validation Errors (400) ​

Error MessageCauseSolution
Phone number must be in E.164 formatInvalid phone formatUse format: +26878422613
Invalid channel. Must be one of: sms, whatsapp, emailInvalid channel valueUse valid channel names
Missing required field: content.textMissing message contentInclude message text
Email already existsDuplicate email on signupUse different email or login
Password must be at least 8 charactersWeak passwordUse stronger password
Invalid date formatDate not in ISO 8601Use: 2025-11-02T12:00:00Z
Limit must be between 1 and 100Invalid pagination limitUse value 1-100

Authentication Errors (401) ​

Error MessageCauseSolution
Invalid API keyWrong or malformed keyCheck API key value
API key has been deactivatedDeactivated keyCreate new API key
Invalid or expired tokenExpired JWTLogin again
Missing X-API-Key headerNo auth headerAdd authentication header

Payment Errors (402) ​

Error MessageCauseSolution
Insufficient credits. You need X but have YLow credit balancePurchase credits
Credit purchase failedPayment issueCheck payment method

Best Practices ​

1. Always Check Response Status ​

javascript
const response = await fetch('https://api.yebolink.com/api/v1/messages/send', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.YEBOLINK_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(messageData)
});

if (!response.ok) {
  const error = await response.json();
  throw new Error(`API Error (${response.status}): ${error.error}`);
}

const data = await response.json();
python
import requests

response = requests.post(
    'https://api.yebolink.com/api/v1/messages/send',
    headers={'X-API-Key': os.environ['YEBOLINK_API_KEY']},
    json=message_data
)

if not response.ok:
    error_data = response.json()
    raise Exception(f"API Error ({response.status_code}): {error_data['error']}")

data = response.json()
php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.yebolink.com/api/v1/messages/send',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: ' . getenv('YEBOLINK_API_KEY'),
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode($messageData)
]);

$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

if ($httpCode !== 200 && $httpCode !== 201) {
    $error = json_decode($response, true);
    throw new Exception("API Error ($httpCode): " . $error['error']);
}

$data = json_decode($response, true);
?>
go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

type ErrorResponse struct {
    Success bool   `json:"success"`
    Error   string `json:"error"`
}

func sendMessage(data map[string]interface{}) error {
    jsonData, _ := json.Marshal(data)

    req, _ := http.NewRequest("POST",
        "https://api.yebolink.com/api/v1/messages/send",
        bytes.NewBuffer(jsonData))

    req.Header.Set("X-API-Key", os.Getenv("YEBOLINK_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 && resp.StatusCode != 201 {
        var errResp ErrorResponse
        body, _ := io.ReadAll(resp.Body)
        json.Unmarshal(body, &errResp)
        return fmt.Errorf("API Error (%d): %s", resp.StatusCode, errResp.Error)
    }

    return nil
}

2. Implement Retry Logic ​

javascript
async function apiCallWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      // Don't retry client errors (4xx except 429)
      if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        throw new Error(`Client error: ${response.status}`);
      }

      // Retry on 429 or 5xx
      if (response.status === 429 || response.status >= 500) {
        if (attempt < maxRetries - 1) {
          const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }

      return await response.json();
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
    }
  }
}

3. Validate Data Before Sending ​

javascript
function validatePhoneNumber(phone) {
  // E.164 format: +[country code][number]
  const e164Regex = /^\+[1-9]\d{1,14}$/;
  return e164Regex.test(phone);
}

function validateMessageData(data) {
  if (!data.to || !validatePhoneNumber(data.to)) {
    throw new Error('Invalid phone number. Use E.164 format: +26878422613');
  }

  if (!['sms', 'whatsapp', 'email'].includes(data.channel)) {
    throw new Error('Invalid channel. Must be: sms, whatsapp, or email');
  }

  if (!data.content || !data.content.text) {
    throw new Error('Message text is required');
  }
}

4. Handle Specific Error Types ​

javascript
async function sendMessage(messageData) {
  try {
    const response = await fetch('https://api.yebolink.com/api/v1/messages/send', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.YEBOLINK_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(messageData)
    });

    const data = await response.json();

    switch (response.status) {
      case 200:
      case 201:
        return data;

      case 400:
        console.error('Validation error:', data.error);
        // Fix the data and retry
        break;

      case 401:
        console.error('Authentication failed:', data.error);
        // Refresh API key
        break;

      case 402:
        console.error('Insufficient credits:', data.error);
        // Redirect to billing
        break;

      case 429:
        console.error('Rate limited:', data.error);
        // Implement backoff and retry
        break;

      case 500:
        console.error('Server error:', data.error);
        // Retry after delay
        break;

      default:
        console.error('Unexpected error:', response.status, data.error);
    }

    throw new Error(data.error);
  } catch (error) {
    console.error('Request failed:', error);
    throw error;
  }
}

Testing Errors ​

You can test error handling using invalid data:

bash
# Test 400 - Invalid phone number
curl -X POST https://api.yebolink.com/api/v1/messages/send \
  -H "X-API-Key: ybk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"to": "invalid", "channel": "sms", "content": {"text": "Test"}}'

# Test 401 - Invalid API key
curl -X POST https://api.yebolink.com/api/v1/messages/send \
  -H "X-API-Key: invalid_key" \
  -H "Content-Type: application/json" \
  -d '{"to": "+26878422613", "channel": "sms", "content": {"text": "Test"}}'

Need Help? ​

If you encounter an error not covered here:

  1. Check the error message carefully
  2. Verify your request parameters
  3. Review the API Reference
  4. Contact support: support@yebolink.app

Built with VitePress