Skip to content

Authentication

Maraboo API uses HMAC-SHA256 authentication to ensure secure access to your resources. This guide explains how authentication works and how to properly authenticate your API requests.

Overview

All API requests to Maraboo must be authenticated using an API token with HMAC-SHA256 signature. This ensures that:

  • Requests are coming from verified sources
  • Data integrity is maintained during transmission
  • Unauthorized access is prevented

Required Headers

Every API request must include the following headers:

http
Authorization: HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY
X-Origin: third-party-api
X-Timestamp: 2025-10-11T21:30:00.000Z
Content-Type: application/json

Header Descriptions

HeaderValueDescription
AuthorizationHMAC-SHA256 PUBLIC_KEY:PRIVATE_KEYAPI key pair (public and private keys) with HMAC-SHA256 prefix
X-Originthird-party-apiRequired origin identifier for all third-party API requests
X-TimestampCurrent timestamp (ISO 8601)Current time in ISO 8601 format (e.g., 2025-10-11T21:30:00.000Z)
Content-Typeapplication/jsonRequest content type

Important

All three headers (Authorization, X-Origin, and X-Timestamp) are mandatory for all requests. Requests missing any of these headers will be rejected with a 401 Unauthorized or 403 Forbidden response.

How API Authentication Works

Maraboo uses a Service Account and API Key system for authentication:

Step 1: Create a Service Account

Service Accounts provide scoped access for automated systems and integrations.

To create a Service Account:

  1. Log in to the Business Portal
  2. Navigate to Developers > Service Accounts
  3. Click "Create Service Account"
  4. Provide a name and description for the service account
  5. Save the service account

Service Accounts Page

Service Account Features:

  • Separate credentials per service/application
  • Can be disabled without affecting other services
  • Supports multiple API keys (one active key at a time)

Step 2: Generate API Keys for the Service Account

Once you have a service account, you need to generate an API key pair.

To generate API Keys:

  1. Navigate to Developers > API Keys
  2. Select the service account you created
  3. Click "Generate API Key"
  4. Both the Public Key and Private Key will be displayed

API Keys Management Page

Save Your Keys Immediately!

The Private Key will only be shown ONCE during generation. You must save both keys securely at this time, as you won't be able to view the private key again. If you lose the private key, you'll need to regenerate a new key pair.

API Key Characteristics:

  • One active key per service account at any given time
  • Public/Private key pair (both required for authentication)
  • Keys can be regenerated when needed
  • Keys can be revoked immediately if compromised
  • Private key is only shown once upon creation

Step 3: Use API Keys in Your Requests

Include your API key pair in every request using the Authorization header:

http
Authorization: HMAC-SHA256 YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY

The format is: HMAC-SHA256 followed by your public key and private key separated by a colon (:).

HMAC-SHA256 Authentication

What is HMAC-SHA256?

HMAC (Hash-based Message Authentication Code) with SHA-256 is a cryptographic authentication method. In Maraboo's implementation:

  • HMAC-SHA256 is the authentication scheme identifier
  • Your API keys (public and private key pair) serve as the authentication credentials
  • The keys ensure requests are coming from verified sources
  • The timestamp header prevents replay attacks

How It Works

  1. Create Service Account: Set up a service account with appropriate permissions
  2. Generate API Key Pair: Create public and private keys for the service account
  3. Include Keys in Header: Add both keys to the Authorization header in format HMAC-SHA256 PUBLIC_KEY:PRIVATE_KEY
  4. Add Timestamp: Include current ISO 8601 timestamp in X-Timestamp header
  5. Add Origin: Include third-party-api in X-Origin header
  6. Send Request: Make the API request with all required headers
  7. Server Validates: Maraboo verifies the key pair and timestamp

TIP

All three headers (Authorization, X-Origin, and X-Timestamp) must be present in every request. See the Code Examples section below for language-specific implementations.

API Key Lifecycle

Key Generation

API keys are generated through the Business Portal when you create them for a service account.

Steps to generate API keys:

  1. Log in to the Business Portal
  2. Create or select a service account at Developers > Service Accounts
  3. Navigate to Developers > API Keys
  4. Generate a new API key for your service account
  5. Immediately save both the public and private keys (private key won't be shown again)

Key Storage

Security Best Practice

Never hardcode API keys in your source code or commit them to version control. Both the public and private keys should be stored securely.

Recommended storage methods:

  • Environment Variables: Store keys in .env files (excluded from version control)
  • Secret Management Services: Use AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, etc.
  • Configuration Management: Use secure configuration management tools

Example - Environment Variables:

bash
# .env file (never commit this file)
MARABOO_PUBLIC_KEY=your_public_key_here
MARABOO_PRIVATE_KEY=your_private_key_here
MARABOO_API_URL=https://gateway.mara.boo

Key Expiry and Rotation

API keys must be rotated periodically to maintain security.

Key Expiry:

  • Keys must be rotated regularly (rotation period: TBD)
  • You will receive email notifications before your keys expire
  • Expired keys will stop working and must be regenerated

Key Rotation Process:

  1. Generate a new API key for your service account in the Business Portal
  2. Save the new keys (public and private) immediately
  3. Update your application with the new key pair
  4. Test thoroughly in your staging/sandbox environment
  5. Deploy to production with the new keys
  6. Revoke the old key after successful deployment and verification

Rotation Best Practices

Rotate API keys:

  • ✅ Before the expiry notification deadline
  • ✅ Immediately if a key is compromised or exposed
  • ✅ When an employee with key access leaves the organization
  • ✅ After a security incident
  • ✅ As part of regular security audits

Important: Since each service account can only have one active key at a time, ensure your rotation process is smooth to avoid service interruptions.

Key Regeneration

If you lose your private key or need to rotate keys, you can regenerate them:

  1. Navigate to Developers > API Keys
  2. Select your service account
  3. Click "the regenerate icon"
  4. The old key pair will be revoked
  5. A new public and private key pair will be generated
  6. Save both keys immediately (private key won't be shown again)

Service Disruption

Regenerating keys will immediately revoke the old key pair. Ensure you have a plan to update all services using the old keys to prevent disruptions.

Key Revocation

You can revoke API keys at any time if they're compromised or no longer needed:

  1. Navigate to Developers > API Keys
  2. Select the service account
  3. Click "toggle the service account and api key off."
  4. The key pair will be immediately invalidated
  5. All requests using the revoked keys will fail

When to revoke keys:

  • Keys have been exposed or compromised
  • Service account is no longer in use
  • Employee with key access has left
  • As part of security incident response

Code Examples

Here are examples of how to authenticate and make API requests in different programming languages:

javascript
const MARABOO_PUBLIC_KEY = process.env.MARABOO_PUBLIC_KEY;
const MARABOO_PRIVATE_KEY = process.env.MARABOO_PRIVATE_KEY;
const BASE_URL = 'https://gateway.mara.boo';

async function getWallets() {
  // Generate current timestamp in ISO 8601 format
  const timestamp = new Date().toISOString();

  const response = await fetch(`${BASE_URL}/api-access/purses/wallets`, {
    method: 'GET',
    headers: {
      'Authorization': `HMAC-SHA256 ${MARABOO_PUBLIC_KEY}:${MARABOO_PRIVATE_KEY}`,
      'X-Origin': 'third-party-api',
      'X-Timestamp': timestamp,
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    throw new Error(`API request failed: ${response.status}`);
  }

  return await response.json();
}

// Usage
try {
  const wallets = await getWallets();
  console.log('Wallets:', wallets);
} catch (error) {
  console.error('Error fetching wallets:', error);
}
python
import os
import requests
from datetime import datetime, timezone

MARABOO_PUBLIC_KEY = os.getenv('MARABOO_PUBLIC_KEY')
MARABOO_PRIVATE_KEY = os.getenv('MARABOO_PRIVATE_KEY')
BASE_URL = 'https://gateway.mara.boo'

def get_wallets():
    """Fetch all wallets for the authenticated business."""
    # Generate current timestamp in ISO 8601 format
    timestamp = datetime.now(timezone.utc).isoformat()

    headers = {
        'Authorization': f'HMAC-SHA256 {MARABOO_PUBLIC_KEY}:{MARABOO_PRIVATE_KEY}',
        'X-Origin': 'third-party-api',
        'X-Timestamp': timestamp,
        'Content-Type': 'application/json'
    }

    response = requests.get(
        f'{BASE_URL}/api-access/purses/wallets',
        headers=headers
    )

    response.raise_for_status()
    return response.json()

# Usage
try:
    wallets = get_wallets()
    print('Wallets:', wallets)
except requests.exceptions.RequestException as error:
    print(f'Error fetching wallets: {error}')
java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;

public class MarabooClient {
    private static final String MARABOO_PUBLIC_KEY = System.getenv("MARABOO_PUBLIC_KEY");
    private static final String MARABOO_PRIVATE_KEY = System.getenv("MARABOO_PRIVATE_KEY");
    private static final String BASE_URL = "https://gateway.mara.boo";

    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        // Generate current timestamp in ISO 8601 format
        String timestamp = Instant.now().toString();

        // Format: HMAC-SHA256 PUBLIC_KEY:PRIVATE_KEY
        String authHeader = "HMAC-SHA256 " + MARABOO_PUBLIC_KEY + ":" + MARABOO_PRIVATE_KEY;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(BASE_URL + "/api-access/purses/wallets"))
            .header("Authorization", authHeader)
            .header("X-Origin", "third-party-api")
            .header("X-Timestamp", timestamp)
            .header("Content-Type", "application/json")
            .GET()
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() == 200) {
            System.out.println("Wallets: " + response.body());
        } else {
            System.err.println("Error: " + response.statusCode());
        }
    }
}
csharp
using System;
using System.Net.Http;
using System.Threading.Tasks;

public class MarabooClient
{
    private static readonly string MARABOO_PUBLIC_KEY = Environment.GetEnvironmentVariable("MARABOO_PUBLIC_KEY");
    private static readonly string MARABOO_PRIVATE_KEY = Environment.GetEnvironmentVariable("MARABOO_PRIVATE_KEY");
    private static readonly string BASE_URL = "https://gateway.mara.boo";

    public static async Task Main(string[] args)
    {
        using var client = new HttpClient();

        // Generate current timestamp in ISO 8601 format
        string timestamp = DateTime.UtcNow.ToString("o");

        // Set up headers
        client.DefaultRequestHeaders.Add("Authorization",
            $"HMAC-SHA256 {MARABOO_PUBLIC_KEY}:{MARABOO_PRIVATE_KEY}");
        client.DefaultRequestHeaders.Add("X-Origin", "third-party-api");
        client.DefaultRequestHeaders.Add("X-Timestamp", timestamp);
        client.DefaultRequestHeaders.Add("Content-Type", "application/json");

        try
        {
            var response = await client.GetAsync($"{BASE_URL}/api-access/purses/wallets");
            response.EnsureSuccessStatusCode();

            string responseBody = await response.Content.ReadAsStringAsync();
            Console.WriteLine($"Wallets: {responseBody}");
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Error fetching wallets: {e.Message}");
        }
    }
}
go
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func main() {
    publicKey := os.Getenv("MARABOO_PUBLIC_KEY")
    privateKey := os.Getenv("MARABOO_PRIVATE_KEY")
    baseURL := "https://gateway.mara.boo"

    // Generate current timestamp in ISO 8601 format
    timestamp := time.Now().UTC().Format(time.RFC3339Nano)

    // Create request
    req, err := http.NewRequest("GET", baseURL+"/api-access/purses/wallets", nil)
    if err != nil {
        fmt.Printf("Error creating request: %v\n", err)
        return
    }

    // Set headers
    req.Header.Set("Authorization", fmt.Sprintf("HMAC-SHA256 %s:%s", publicKey, privateKey))
    req.Header.Set("X-Origin", "third-party-api")
    req.Header.Set("X-Timestamp", timestamp)
    req.Header.Set("Content-Type", "application/json")

    // Send request
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error fetching wallets: %v\n", err)
        return
    }
    defer resp.Body.Close()

    // Read response
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response: %v\n", err)
        return
    }

    fmt.Printf("Wallets: %s\n", string(body))
}
bash
#!/bin/bash

MARABOO_PUBLIC_KEY="${MARABOO_PUBLIC_KEY}"
MARABOO_PRIVATE_KEY="${MARABOO_PRIVATE_KEY}"
BASE_URL="https://gateway.mara.boo"

# Generate current timestamp in ISO 8601 format
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")

# Get Wallets
curl -X GET "${BASE_URL}/api-access/purses/wallets" \
  -H "Authorization: HMAC-SHA256 ${MARABOO_PUBLIC_KEY}:${MARABOO_PRIVATE_KEY}" \
  -H "X-Origin: third-party-api" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "Content-Type: application/json"

Error Handling

Common Authentication Errors

Status CodeErrorCauseSolution
401 UnauthorizedInvalid or missing authenticationToken is invalid, expired, or missingVerify token is correct and included in header
403 ForbiddenMissing X-Origin headerRequired X-Origin header not includedAdd X-Origin: third-party-api to all requests
403 ForbiddenInsufficient permissionsToken doesn't have required permissionsCheck service account permissions in portal
429 Too Many RequestsRate limit exceededToo many requests in short timeImplement exponential backoff retry logic

Example Error Response

json
{
  "success": false,
  "message": "Authentication failed",
  "detail": "Invalid or missing authorization header",
  "error_code": "AUTH_001"
}

Security Best Practices

1. Secure Token Storage

  • ✅ Store tokens in environment variables or secret management systems
  • ✅ Use secure configuration management
  • ❌ Never hardcode tokens in source code
  • ❌ Never commit tokens to version control

2. Use HTTPS Only

  • ✅ Always use https:// for API requests
  • ❌ Never send tokens over unencrypted http:// connections

3. Implement Token Rotation

  • ✅ Rotate tokens regularly (every 90 days minimum)
  • ✅ Have a process for emergency rotation
  • ✅ Test new tokens before revoking old ones

4. Separate Service Accounts

  • ✅ Create separate service accounts for different services/applications
  • ✅ Regularly audit and remove unused service accounts
  • ✅ Disable service accounts immediately when no longer needed

5. Monitor and Log

  • ✅ Monitor API usage for unusual patterns
  • ✅ Log authentication failures
  • ✅ Set up alerts for suspicious activity
  • ❌ Never log full API tokens

6. IP Whitelisting

  • ✅ Provide your server IP addresses during API access request
  • ✅ Update whitelisted IPs when infrastructure changes
  • ✅ Use static IPs for production services

7. Emergency Response Plan

Have a plan for when keys are compromised:

Immediate actions:

  1. 🔴 Revoke the compromised key immediately
  2. 🔴 Regenerate a new key pair
  3. 🔴 Update all services with new keys
  4. 🔴 Monitor for unauthorized access attempts
  5. 🔴 Investigate how the key was exposed
  6. 🔴 Document the incident and response

Testing Authentication

Sandbox Environment

Test your authentication setup in the sandbox environment before going to production:

javascript
// Use sandbox URL for testing
const BASE_URL = 'https://sandbox.mara.boo';

// Use sandbox API token
const SANDBOX_TOKEN = process.env.MARABOO_SANDBOX_TOKEN;

Verify Authentication

Use the Get Wallets endpoint as a simple authentication test:

bash
# Generate timestamp
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")

curl -X GET https://sandbox.mara.boo/api-access/purses/wallets \
  -H "Authorization: HMAC-SHA256 ${SANDBOX_PUBLIC_KEY}:${SANDBOX_PRIVATE_KEY}" \
  -H "X-Origin: third-party-api" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "Content-Type: application/json"

A successful response (status 200) indicates your authentication is working correctly.

Next Steps