Introduction

Welcome to the TONE3000 API. This RESTful API provides programmatic access to TONE3000 accounts, tones and models. To use the API, you or your users will need to authenticate via their TONE3000 account.

Note: This is version 1 of our API. Endpoints and data structures may change as we improve the platform.

Quick Start

  1. Authenticate users through our OAuth-style flow
  2. Use access tokens to make requests to https://www.tone3000.com/api/v1/
  3. Query user profile, created tones, favorited tones, and model data

Rate Limit

100 requests per minute by default. For production applications please email support@tone3000.com.

Support & Feedback

Questions, issues, or feedback? Contact support@tone3000.com - we'd love to hear from you.

Authentication

Initial Setup

1. Redirect users to the TONE3000 authentication page

Start the authentication flow by redirecting users to the TONE3000 authentication page. Make sure to encode your application's URL as the redirect_url parameter.

Note: If your application only supports OTP authentication (e.g. IOT devices), include otp_only=true in the search parameters. This will send the user a 6-digit OTP code instead of a magic link.

import { APP_URL } from '@/config/constants';
const redirectUrl = encodeURIComponent(APP_URL);
window.location.href = `https://www.tone3000.com/api/v1/auth?redirect_url=${redirectUrl}`;
  • Search parameters:
    NameTypeDescription
    redirect_urlstringThe URL to redirect to after authentication.
    otp_onlybooleanIf true, the user will be sent a 6-digit OTP code instead of a magic link.
  • 2. Exchange API Key for Session Tokens

    After successful authentication, TONE3000 will redirect back to your application's redirect_url with an api_key parameter. You'll need to exchange this API key for session tokens. The response will include access and refresh tokens, along with expiration information.

    // Get API key from URL search params
    const urlParams = new URLSearchParams(window.location.search);
    const apiKey = urlParams.get('api_key');
    const response = await fetch('https://www.tone3000.com/api/v1/auth/session', {
    method: 'POST',
    body: JSON.stringify({ api_key: apiKey })
    });
    const data = await response.json();

    Session Management

    1. Store Session Tokens

    After exchanging the API key, you'll receive an access token and refresh token. Store these tokens securely in your application (e.g., in localStorage for web apps). Also store the expiration time to enable proactive token refresh.

    // Store tokens and expiration
    localStorage.setItem('tone3000_access_token', data.access_token);
    localStorage.setItem('tone3000_refresh_token', data.refresh_token);
    localStorage.setItem('tone3000_expires_at', String(Date.now() + (data.expires_in * 1000)));

    2. Making Authenticated Requests

    Include the access token in the Authorization header for all API requests. The token should be prefixed with "Bearer ". Before making a request, check if the token is about to expire and refresh it if needed.

    // Check if token needs refresh
    const expiresAt = parseInt(localStorage.getItem('tone3000_expires_at') || '0');
    if (Date.now() > expiresAt) {
    await refreshTokens();
    }
    const response = await fetch(url, {
    headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
    }
    });

    3. Token Refresh Flow

    When an API request returns 401 (Unauthorized) or when proactively refreshing, use the refresh token to get a new access token. The response will include new tokens and expiration information.

    // Refresh the access token
    const refreshResponse = await fetch('https://www.tone3000.com/api/v1/auth/session/refresh', {
    method: 'POST',
    body: JSON.stringify({
    refresh_token: refreshToken,
    access_token: accessToken
    })
    });
    const newTokens = await refreshResponse.json();
    // Store the new tokens and expiration
    localStorage.setItem('tone3000_access_token', newTokens.access_token);
    localStorage.setItem('tone3000_refresh_token', newTokens.refresh_token);
    localStorage.setItem('tone3000_expires_at', String(Date.now() + (newTokens.expires_in * 1000)));

    4. Handling Refresh Failure

    If token refresh fails (e.g., refresh token is expired), clear the stored tokens and redirect the user back to the authentication page to restart the authentication flow.

    // Clear stored tokens
    localStorage.removeItem('tone3000_access_token');
    localStorage.removeItem('tone3000_refresh_token');
    localStorage.removeItem('tone3000_expires_at');
    // Redirect back to auth page to restart authentication
    const redirectUrl = encodeURIComponent(window.location.href);
    window.location.href = `https://www.tone3000.com/api/v1/auth?redirect_url=${redirectUrl}`;

    User

    Get information about the currently authenticated user.

    const response = await fetch('https://www.tone3000.com/api/v1/user', {
    headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
    }
    });
    const user = await response.json();

    Tones

    Created Tones

    Get a list of tones created by the currently authenticated user.

    const response = await fetch(`https://www.tone3000.com/api/v1/tones/created?page=${page}&pageSize=${pageSize}`, {
    headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
    }
    });
    const tones = await response.json();
    • Response type: PaginatedResponse<Tones[]>
    • Query parameters:
      NameTypeDescription
      pagenumberPage number for pagination (default: 1, optional)
      pageSizenumberNumber of items per page (default: 10, max: 100, optional)

    Favorited Tones

    Get a list of tones favorited by the currently authenticated user.

    const response = await fetch(`https://www.tone3000.com/api/v1/tones/favorited?page=${page}&pageSize=${pageSize}`, {
    headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
    }
    });
    const tones = await response.json();
    • Response type: PaginatedResponse<Tones[]>
    • Query parameters:
      NameTypeDescription
      pagenumberPage number for pagination (default: 1, optional)
      pageSizenumberNumber of items per page (default: 10, max: 100, optional)

    Models

    Get a list of models for a specific tone accessible by the current authenticated user.

    const response = await fetch(`https://www.tone3000.com/api/v1/models?toneId=${toneId}&page=${page}&pageSize=${pageSize}`, {
    headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
    }
    });
    const models = await response.json();
    • Response type: PaginatedResponse<Model[]>
    • Query parameters:
      NameTypeDescription
      toneIdnumberID of the tone to get models for
      pagenumberPage number for pagination (default: 1, optional)
      pageSizenumberNumber of items per page (default: 10, max: 100, optional)

    The model_url field can be used to download the model. It is only accessible to the owner of the model and users who have favorited the tone.

    // Download model in browser
    const downloadModel = async (modelUrl: string) => {
    const response = await fetch(modelUrl, {
    headers: {
    'Authorization': `Bearer ${accessToken}`
    }
    });
    if (!response.ok) {
    throw new Error('Failed to download model');
    }
    const blob = await response.blob();
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = modelUrl.split('/').pop() || 'model';
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
    };
    // Usage
    await downloadModel(model.model_url);

    Enums

    Gear

    enum Gear {
    Amp = 'amp',
    FullRig = 'full-rig',
    Pedal = 'pedal',
    Outboard = 'outboard',
    Ir = 'ir'
    }

    Platforms

    enum Platform {
    Nam = 'nam',
    Ir = 'ir',
    AidaX = 'aida-x',
    AaSnapshot = 'aa-snapshot',
    Proteus = 'proteus'
    }

    Licenses

    enum License {
    T3k = 't3k',
    CcBy = 'cc-by',
    CcBySa = 'cc-by-sa',
    CcByNc = 'cc-by-nc',
    CcByNcSa = 'cc-by-nc-sa',
    CcByNd = 'cc-by-nd',
    CcByNcNd = 'cc-by-nc-nd',
    Cco = 'cco'
    }

    Sizes

    enum Size {
    Standard = 'standard',
    Lite = 'lite',
    Feather = 'feather',
    Nano = 'nano',
    Custom = 'custom'
    }

    Types

    Session

    The response type for both session creation and refresh endpoints.

    interface Session {
    access_token: string;
    refresh_token: string;
    expires_in: number; // seconds until token expires
    token_type: 'bearer';
    }

    EmbeddedUser

    interface EmbeddedUser {
    id: string;
    username: string;
    avatar_url: string | null;
    url: string;
    }

    User

    interface User extends EmbeddedUser {
    bio: string | null;
    links: string[] | null;
    created_at: string;
    updated_at: string;
    }

    Make

    interface Make {
    id: number;
    name: string;
    }

    Tag

    interface Tag {
    id: number;
    name: string;
    }

    Paginated Response

    interface PaginatedResponse<T> {
    data: T[];
    page: number;
    pageSize: number;
    total: number;
    totalPages: number;
    }

    Tone

    interface Tone {
    id: number;
    user_id: string;
    user: EmbeddedUser;
    created_at: string;
    updated_at: string;
    title: string;
    description: string | null;
    gear: Gear;
    images: string[] | null;
    is_public: boolean | null;
    links: string[] | null;
    platform: Platform;
    license: License;
    sizes: Size[];
    makes: Make[];
    tags: Tag[];
    models_count: number;
    downloads_count: number;
    favorites_count: number;
    url: string;
    }

    Model

    interface Model {
    id: number;
    created_at: string;
    updated_at: string;
    user_id: string;
    model_url: string;
    name: string;
    size: Size;
    tone_id: number;
    }

    Example

    For a complete end-to-end example of how to use the TONE3000 API in a React application, check out our example repository. This repository demonstrates:

    • User authentication and session management
    • Fetching and displaying user data
    • Working with tones and models
    • Handling API responses and errors
    • Token refresh flow implementation

    The example app uses the t3kFetch utility to handle authentication and token management automatically.

    // Example: Fetching user data
    const response = await t3kFetch('https://www.tone3000.com/api/v1/user');
    const userData = await response.json();