Skip to main content

Overview

BlockDB uses OAuth 2.0 with JWT bearer tokens for API authentication. All requests must include a valid token in the Authorization header. Tokens are scoped to specific datasets, chains, and rate limits.

Authentication Flow

1

Request Access

Contact support@blockdb.io to request API access. Provide:
  • Your organization name
  • Intended use case
  • Required datasets and chains
  • Expected request volume
2

Receive Credentials

You’ll receive:
  • Client ID and Client Secret for token generation (OAuth 2.0 Client Credentials)
  • Scopes defining your access permissions (e.g. offline_access api)
  • Rate limits based on your plan
3

Generate JWT Token

Use your client_id and client_secret to request a JWT token from the UserService authentication endpoint (Client Credentials flow). Use the Code examples below to obtain the JWT Access Token.
4

Include in Requests

Send the token in the Authorization header with every API request:
Authorization: Bearer <your_jwt_token>
The token is valid for 15 minutes. For production applications, use a token refresh mechanism that automatically renews tokens before expiration.

Code examples: generate the JWT Access Token

The token is obtained from https://user.blockdb.io/api/authorization/token using OAuth 2.0 Client Credentials (Basic auth with client_id and client_secret). Scopes: offline_access api. Use the Access Token when calling https://api.blockdb.io.
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

var tokenUrl = "https://user.blockdb.io/api/authorization/token";
var clientId = "<CLIENT_ID>";
var clientSecret = "<CLIENT_SECRET>";
var scope = "offline_access api";

using var http = new HttpClient();
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);

var body = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("grant_type", "client_credentials"),
    new KeyValuePair<string, string>("scope", scope)
});

var res = await http.PostAsync(tokenUrl, body);
res.EnsureSuccessStatusCode();
var json = await res.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(json);
var accessToken = doc.RootElement.GetProperty("access_token").GetString();
var refreshToken = doc.RootElement.TryGetProperty("refresh_token", out var rt) ? rt.GetString() : null;

Console.WriteLine("Access Token: " + accessToken);
if (!string.IsNullOrEmpty(refreshToken))
    Console.WriteLine("Refresh Token: " + refreshToken);

Code examples: token + refresh + get blocks

Tokens are obtained from https://user.blockdb.io/api/authorization/token using OAuth 2.0 Client Credentials (client_id and client_secret). Scopes: offline_access api. Use the token when calling https://api.blockdb.io. Refresh the token every 15 minutes; the examples use a background task that re-requests a token (refresh_token grant if available, otherwise client_credentials).
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

const string TokenUrl = "https://user.blockdb.io/api/authorization/token";
const string Scope = "offline_access api";

var clientId = "<BLOCKDB_CLIENT_ID>";
var clientSecret = "<BLOCKDB_CLIENT_SECRET>";

if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret))
{
    Console.WriteLine("Set BLOCKDB_CLIENT_ID and BLOCKDB_CLIENT_SECRET");
    return 1;
}

var tokenHolder = new TokenHolder();
using var http = new HttpClient();

var tokens = await RequestClientCredentialsTokenAsync(clientId!, clientSecret!);
if (tokens == null) { Console.WriteLine("Failed to get initial token."); return 1; }
tokenHolder.Set(tokens.Value.AccessToken!, tokens.Value.RefreshToken ?? "");

// Background: refresh token every 14 minutes (refresh_token if available, else client_credentials)
_ = Task.Run(async () =>
{
    while (true)
    {
        await Task.Delay(TimeSpan.FromMinutes(14));
        try
        {
            var refreshToken = tokenHolder.GetRefreshToken();
            TokenResult? newTokens = null;
            if (!string.IsNullOrEmpty(refreshToken))
                newTokens = await RequestRefreshTokenAsync(clientId!, clientSecret!, refreshToken);
            if (newTokens == null)
                newTokens = await RequestClientCredentialsTokenAsync(clientId!, clientSecret!);
            if (newTokens != null)
                tokenHolder.Set(newTokens.Value.AccessToken, newTokens.Value.RefreshToken ?? refreshToken ?? "");
        }
        catch (Exception ex) { Console.WriteLine("Token refresh failed: " + ex.Message); }
    }
});

// Main: get blocks every 1 min
while (true)
{
    var response = await GetBlocksAsync(http, tokenHolder.GetAccessToken());
    response.EnsureSuccessStatusCode();
    Console.WriteLine($"[{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC] {await response.Content.ReadAsStringAsync()}");
    await Task.Delay(TimeSpan.FromMinutes(1));
}

async Task<TokenResult?> RequestClientCredentialsTokenAsync(string clientId, string clientSecret)
{
    var body = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("grant_type", "client_credentials"),
        new KeyValuePair<string, string>("scope", Scope)
    });
    return await PostTokenRequestAsync(clientId, clientSecret, body);
}

async Task<TokenResult?> RequestRefreshTokenAsync(string clientId, string clientSecret, string refreshToken)
{
    var body = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("grant_type", "refresh_token"),
        new KeyValuePair<string, string>("refresh_token", refreshToken)
    });
    return await PostTokenRequestAsync(clientId, clientSecret, body);
}

async Task<TokenResult?> PostTokenRequestAsync(string clientId, string clientSecret, HttpContent body)
{
    var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
    using var tokenClient = new HttpClient();
    tokenClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
    var res = await tokenClient.PostAsync(TokenUrl, body);
    if (!res.IsSuccessStatusCode) return null;
    var json = await res.Content.ReadAsStringAsync();
    var doc = JsonDocument.Parse(json);
    var root = doc.RootElement;
    var accessToken = root.TryGetProperty("access_token", out var at) ? at.GetString() : null;
    var refreshToken = root.TryGetProperty("refresh_token", out var rt) ? rt.GetString() : null;
    if (string.IsNullOrEmpty(accessToken)) return null;
    return new TokenResult(accessToken, refreshToken);
}

async Task<HttpResponseMessage> GetBlocksAsync(HttpClient http, string token)
{
    var req = new HttpRequestMessage(HttpMethod.Post, "https://api.blockdb.io/v1/evm/raw/blocks");
    req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
    req.Content = new StringContent("{\"chain_id\":1,\"from_block\":12345678,\"to_block\":12345999,\"limit\":10}", Encoding.UTF8, "application/json");
    return await http.SendAsync(req);
}

readonly record struct TokenResult(string AccessToken, string? RefreshToken);

class TokenHolder
{
    private string _accessToken = "";
    private string _refreshToken = "";
    private readonly object _lock = new();
    public void Set(string accessToken, string refreshToken) { lock (_lock) { _accessToken = accessToken; _refreshToken = refreshToken ?? ""; } }
    public string GetAccessToken() { lock (_lock) { return _accessToken; } }
    public string GetRefreshToken() { lock (_lock) { return _refreshToken; } }
}

See Also

curl -X POST 'https://api.blockdb.io/v1/evm/raw/blocks' \
  -H 'Authorization: Bearer <Access Token from the previous example>' \
  -H 'Content-Type: application/json' \
  -d '{
    "chain_id": 1,
    "from_block": 12345678,
    "to_block": 12345999
  }'
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired token",
    "details": "Token expired at 2025-01-15T10:30:00Z"
  }
}