Code Examples

Complete client implementations in Python, JavaScript/Node.js, and C# with automatic token refresh.

Python

import requests
from datetime import datetime, timedelta

class MT2DataClient:
    def __init__(self, client_id: str, client_secret: str):
        self.base_url = "https://datalake.mt2data.cloud"
        self.client_id = client_id
        self.client_secret = client_secret
        self.access_token = None
        self.token_expires_at = None

    def _get_token(self) -> str:
        """Get or refresh access token."""
        if self.access_token and self.token_expires_at > datetime.now():
            return self.access_token

        response = requests.post(
            f"{self.base_url}/oauth/token",
            json={
                "grant_type": "client_credentials",
                "client_id": self.client_id,
                "client_secret": self.client_secret
            }
        )
        response.raise_for_status()

        data = response.json()
        self.access_token = data["access_token"]
        # Refresh 60s before actual expiry
        self.token_expires_at = datetime.now() + timedelta(seconds=data["expires_in"] - 60)
        return self.access_token

    def _headers(self) -> dict:
        return {"Authorization": f"Bearer {self._get_token()}"}

    def get_catalog(self) -> dict:
        """Get all authorized Symbols and descriptions."""
        return requests.get(f"{self.base_url}/catalog", headers=self._headers()).json()

    def list_files(self, limit: int = 1000) -> dict:
        """List accessible files with existence verification (~2s)."""
        return requests.get(
            f"{self.base_url}/list",
            headers=self._headers(),
            params={"limit": limit}
        ).json()

    def count_files(self) -> int:
        """Count total accessible files."""
        return requests.get(f"{self.base_url}/count", headers=self._headers()).json()["count"]

    def get_file_info(self, symbol: str) -> dict:
        """Get metadata for a file by Symbol."""
        return requests.get(f"{self.base_url}/info/{symbol}", headers=self._headers()).json()

    def download_file(self, symbol: str, local_path: str) -> None:
        """Download a file by Symbol to disk."""
        with requests.get(
            f"{self.base_url}/download/{symbol}",
            headers=self._headers(),
            stream=True
        ) as r:
            r.raise_for_status()
            with open(local_path, "wb") as f:
                for chunk in r.iter_content(chunk_size=8192):
                    f.write(chunk)


# Usage
if __name__ == "__main__":
    client = MT2DataClient(
        client_id="your-client-id@company.com",
        client_secret="your-secret-key-here"
    )

    # Browse available files
    catalog = client.get_catalog()
    print(f"Available Symbols: {catalog['count']}")
    for f in catalog["files"][:5]:
        print(f"  {f['Symbol']}: {f['Description']}")

    # Download a file by Symbol
    client.download_file("YOUR_SYMBOL", "dataset.parquet")
    print("Downloaded dataset.parquet")

JavaScript / Node.js

const axios = require('axios');
const fs = require('fs');

class MT2DataClient {
  constructor(clientId, clientSecret) {
    this.baseUrl = 'https://datalake.mt2data.cloud';
    this.clientId = clientId;
    this.clientSecret = clientSecret;
    this.accessToken = null;
    this.tokenExpiresAt = null;
  }

  async _getToken() {
    if (this.accessToken && this.tokenExpiresAt > Date.now()) {
      return this.accessToken;
    }
    const response = await axios.post(`${this.baseUrl}/oauth/token`, {
      grant_type: 'client_credentials',
      client_id: this.clientId,
      client_secret: this.clientSecret
    });
    this.accessToken = response.data.access_token;
    // Refresh 60s before expiry
    this.tokenExpiresAt = Date.now() + (response.data.expires_in - 60) * 1000;
    return this.accessToken;
  }

  async _headers() {
    return { Authorization: `Bearer ${await this._getToken()}` };
  }

  async getCatalog() {
    return (await axios.get(`${this.baseUrl}/catalog`, { headers: await this._headers() })).data;
  }

  async listFiles(limit = 1000) {
    return (await axios.get(`${this.baseUrl}/list`, {
      headers: await this._headers(),
      params: { limit }
    })).data;
  }

  async getFileInfo(symbol) {
    return (await axios.get(`${this.baseUrl}/info/${symbol}`, { headers: await this._headers() })).data;
  }

  async downloadFile(symbol, localPath) {
    const response = await axios.get(`${this.baseUrl}/download/${symbol}`, {
      headers: await this._headers(),
      responseType: 'stream'
    });
    await new Promise((resolve, reject) => {
      response.data.pipe(fs.createWriteStream(localPath))
        .on('finish', resolve)
        .on('error', reject);
    });
  }
}

// Usage
async function main() {
  const client = new MT2DataClient(
    'your-client-id@company.com',
    'your-secret-key-here'
  );

  const catalog = await client.getCatalog();
  console.log(`Available Symbols: ${catalog.count}`);

  await client.downloadFile('YOUR_SYMBOL', 'dataset.parquet');
  console.log('Downloaded dataset.parquet');
}

main().catch(console.error);

C# / .NET

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class MT2DataClient
{
    private readonly string _baseUrl = "https://datalake.mt2data.cloud";
    private readonly string _clientId;
    private readonly string _clientSecret;
    private readonly HttpClient _httpClient = new();
    private string _accessToken;
    private DateTime _tokenExpiresAt;

    public MT2DataClient(string clientId, string clientSecret)
    {
        _clientId = clientId;
        _clientSecret = clientSecret;
    }

    private async Task<string> GetTokenAsync()
    {
        if (_accessToken != null && _tokenExpiresAt > DateTime.UtcNow)
            return _accessToken;

        var content = new StringContent(
            JsonSerializer.Serialize(new {
                grant_type = "client_credentials",
                client_id = _clientId,
                client_secret = _clientSecret
            }),
            Encoding.UTF8, "application/json"
        );

        var response = await _httpClient.PostAsync($"{_baseUrl}/oauth/token", content);
        response.EnsureSuccessStatusCode();

        using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
        _accessToken = doc.RootElement.GetProperty("access_token").GetString();
        var expiresIn = doc.RootElement.GetProperty("expires_in").GetInt32();
        _tokenExpiresAt = DateTime.UtcNow.AddSeconds(expiresIn - 60);
        return _accessToken;
    }

    public async Task<string> GetCatalogAsync()
    {
        var token = await GetTokenAsync();
        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", token);
        var response = await _httpClient.GetAsync($"{_baseUrl}/catalog");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    public async Task DownloadFileAsync(string symbol, string localPath)
    {
        var token = await GetTokenAsync();
        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", token);
        var bytes = await _httpClient.GetByteArrayAsync($"{_baseUrl}/download/{symbol}");
        await System.IO.File.WriteAllBytesAsync(localPath, bytes);
    }
}

// Usage
var client = new MT2DataClient("your-client-id@company.com", "your-secret-key-here");
Console.WriteLine(await client.GetCatalogAsync());
await client.DownloadFileAsync("YOUR_SYMBOL", "dataset.parquet");