DocsBookingAPIAuthentication

Authentication

The BookingAPI uses service-account JWT authentication. You exchange an API key and secret for a short-lived token, then pass that token as a Bearer header on every request.

Get your credentials

Contact your MoovLogic account manager to have a service account created. You will receive:

  • An apiKey — your account identifier (UUID format)
  • An apiSecret — your secret credential
🚨
Keep your secret secure. Store apiSecret in an environment variable or secrets manager. Never commit it to source control or expose it in client-side JavaScript or mobile apps.

Request a token

POST /api/v1/auth/token

Request body

ParameterTypeRequiredDescription
apiKey string (UUID) Required Your API key, provided by MoovLogic.
apiSecret string Required Your API secret, provided by MoovLogic.
Request
curl -X POST https://api.moovlogic.com/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "apiSecret": "YOUR_API_SECRET"
  }'
import requests

response = requests.post(
    'https://api.moovlogic.com/api/v1/auth/token',
    json={
        'apiKey': 'YOUR_API_KEY',
        'apiSecret': 'YOUR_API_SECRET'
    }
)
response.raise_for_status()
token = response.json()['token']
print(f"Token expires in: {response.json()['expiresIn']} seconds")
<?php
$ch = curl_init('https://api.moovlogic.com/api/v1/auth/token');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'apiKey'    => 'YOUR_API_KEY',
        'apiSecret' => 'YOUR_API_SECRET'
    ])
]);
$body  = curl_exec($ch);
$data  = json_decode($body, true);
$token = $data['token'];
curl_close($ch);
const response = await fetch('https://api.moovlogic.com/api/v1/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        apiKey: 'YOUR_API_KEY',
        apiSecret: 'YOUR_API_SECRET'
    })
});

if (!response.ok) throw new Error(`Auth failed: ${response.status}`);
const { token, expiresIn } = await response.json();

Response — 200 OK

Response 200 OK
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcGlfa2V5X2lkIiwiY29tcGFueUlkIjoiMTIzIiwiZXhwIjoxNzE0NjA4MDAwfQ.signature",
  "expiresIn": 86400,
  "tokenType": "Bearer"
}
Response 401 Unauthorized
{
  "error": "invalid_credentials",
  "message": "The API key or secret is incorrect.",
  "requestId": "req_01HZ9VBKX4E..."
}

Use the token

Include the token in the Authorization header on every subsequent request:

Authenticated request
curl https://api.moovlogic.com/api/v1/pricing/service-types \
  -H "Authorization: Bearer YOUR_TOKEN"
headers = {'Authorization': f'Bearer {token}'}
response = requests.get(
    'https://api.moovlogic.com/api/v1/pricing/service-types',
    headers=headers
)
service_types = response.json()['serviceTypes']
<?php
$ch = curl_init('https://api.moovlogic.com/api/v1/pricing/service-types');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ["Authorization: Bearer $token"]
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://api.moovlogic.com/api/v1/pricing/service-types', {
    headers: { 'Authorization': `Bearer ${token}` }
});
const { serviceTypes } = await response.json();

Token expiry and caching

Tokens are valid for 24 hours (expiresIn: 86400 seconds).

💡
Cache the token for 23 hours and refresh proactively rather than waiting for a 401. This avoids failed requests at the exact expiry boundary.
Token cache pattern
import time, requests

_token_cache = {'token': None, 'expires_at': 0}

def get_token():
    if _token_cache['token'] and time.time() < _token_cache['expires_at']:
        return _token_cache['token']
    r = requests.post(
        'https://api.moovlogic.com/api/v1/auth/token',
        json={'apiKey': API_KEY, 'apiSecret': API_SECRET}
    )
    r.raise_for_status()
    data = r.json()
    _token_cache['token']      = data['token']
    _token_cache['expires_at'] = time.time() + (23 * 3600)  # refresh at 23h
    return _token_cache['token']
let cachedToken = null;
let tokenExpiresAt = 0;

async function getToken() {
    if (cachedToken && Date.now() < tokenExpiresAt) return cachedToken;

    const res = await fetch('https://api.moovlogic.com/api/v1/auth/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ apiKey: API_KEY, apiSecret: API_SECRET })
    });
    const { token } = await res.json();
    cachedToken     = token;
    tokenExpiresAt  = Date.now() + (23 * 60 * 60 * 1000); // 23 hours
    return cachedToken;
}