Jump to
Ctrl
+
/

Data Flow Limiting

Overview

Vaultody applies two types of limits to API usage: rate limits (how many requests you can make per time window) and pagination limits (how many items are returned per API response). Both are determined by your subscription plan.

Rate Limiting

Each API is subject to a request rate limit. When you exceed the limit, the API returns:

HTTP 429 Too Many Requests
{
  "requestId": "601c1710034ed6d407996b30",
  "error": {
    "code": "request_limit_reached",
    "message": "The request limit has been reached. There can be maximum {requests} requests per {seconds} second(s) made. Please contact our team via email if you need more or upgrade your plan."
  }
}

Handling 429 Responses

When you receive a 429, back off and retry with increasing delays. Do not retry immediately — this will continue to be rate-limited.

Python — exponential backoff:

import time

def request_with_retry(method, path, body=None, max_retries=4):
    for attempt in range(max_retries):
        response = signed_request(method, path, body)
        if response.status_code == 429:
            wait_seconds = 2 ** attempt  # 1s → 2s → 4s → 8s
            print(f"Rate limited. Retrying in {wait_seconds}s...")
            time.sleep(wait_seconds)
            continue
        return response
    raise Exception("Max retries exceeded after rate limiting")

Node.js — exponential backoff:

async function requestWithRetry(method, path, body = null, maxRetries = 4) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        const response = await signedRequest(method, path, body);
        if (response.status === 429) {
            const wait = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s, 8s
            console.log(`Rate limited. Retrying in ${wait / 1000}s...`);
            await new Promise(r => setTimeout(r, wait));
            continue;
        }
        return response;
    }
    throw new Error('Max retries exceeded after rate limiting');
}

Best practice: Spread your API calls over time where possible. If you are syncing large amounts of data, use pagination and process pages sequentially rather than in parallel.

Pagination

Vaultody uses cursor-based pagination for all list endpoints. Pages are navigated using the ID of the last item you received, not a page number. This approach stays consistent and reliable even when new records are added between requests.

Pagination Parameters

Parameter Type Default Description
limit integer 50 Number of items to return per page. Each endpoint declares its own maximum — 50 unless its reference page states otherwise. Exceeding it returns 409 naming the allowed maximum
startingAfter string The id (or equivalent ID field) of the last item from the previous page. Omit for the first page

How It Works

On the first request, omit startingAfter:

GET /vaults/{vaultId}/vault-accounts/details?limit=50

The response includes a hasMore field:

{
  "apiVersion": "2026-03-20",
  "requestId": "601c1710034ed6d407996b30",
  "data": {
    "limit": 50,
    "hasMore": true,
    "items": [
      {
        "vaultAccountId": "68dfaeae39a4b80007c4f707",
        "vaultAccountName": "User Alice"
      }
    ]
  }
}

If hasMore is true, take the vaultAccountId (or the relevant ID field) of the last item in the array and pass it as startingAfter on the next request:

GET /vaults/{vaultId}/vault-accounts/details?limit=50&startingAfter=68dfaeae39a4b80007c4f707

Repeat until hasMore is false.

Full Pagination Example

Python — fetch all Vault Accounts:

def get_all_vault_accounts(vault_id):
    all_accounts = []
    starting_after = None
    while True:
        params = {'limit': 50}
        if starting_after:
            params['startingAfter'] = starting_after

        resp = signed_request('GET', f'/vaults/{vault_id}/vault-accounts/details', params=params)
        data = resp.json()['data']
        all_accounts.extend(data['items'])

        if not data['hasMore'] or not data['items']:
            break

        # Use the last item's ID as the next cursor
        starting_after = data['items'][-1]['vaultAccountId']

    return all_accounts

Node.js — fetch all Vault Accounts:

async function getAllVaultAccounts(vaultId) {
    const allAccounts = [];
    let startingAfter = null;
    do {
        const params = { limit: 50 };
        if (startingAfter) params.startingAfter = startingAfter;

        const resp = await signedRequest('GET', `/vaults/${vaultId}/vault-accounts/details`, null, params);
        const { items, hasMore } = resp.data.data;
        allAccounts.push(...items);

        startingAfter = hasMore && items.length ? items[items.length - 1].vaultAccountId : null;
    } while (startingAfter !== null);

    return allAccounts;
}

Subscription Tiers

API data flow limits and feature availability are determined by your subscription tier. Higher tiers provide increased rate limits and higher Vault Account caps.

For details on what is included in each plan, visit the Vaultody pricing page or contact us through the Help Center.

Mainnet access is not available on free plans. feature_mainnets_not_allowed_for_plan means your plan is restricted to testnet — upgrade to enable mainnet access. mainnet_not_allowed_for_key means your plan allows mainnet but you used a test API key; create a main API key in the Dashboard.

Was this page helpful?
Yes
No
Powered by