Skip to main content

API Keys

The Tiro API uses API keys for authentication. Every request carries a valid key in the Authorization header as a Bearer token. Each key belongs to a workspace. The key reaches that workspace’s resources — its notes, transcripts, summaries, and folders — and nothing outside it. Pick the workspace first, then create the key.

Key types and permissions

Tiro API keys fall into two types, based on who the request represents.
Key typeHow it is identifiedWhat it can do
User keyThe key is tied to a specific user identity.Use it for read and write operations. Actions that change workspace data, such as creating note documents or changing share links, require a user key.
Workspace system keyThe key is tied to the workspace container without a user.Use it for read access to resources shared with the whole workspace. It cannot perform write operations.
When a workspace system key reads folders, it only returns folders shared with all workspace members. If you need access to private folders, folders shared with specific people, or any create, update, or delete action, create and use a user key instead.
If a workspace system key is not bound to a workspace yet, authentication may fail with 401 Unauthorized. If the key format is correct but 401 responses continue, check which workspace the key is connected to and where it was created.
Legacy personal keys are going away. Personal API keys created before workspaces stop working on June 30, 2026. Create a workspace key and swap it in before then — see Legacy personal keys below.

Getting Your API Key

Create your key from the Tiro Platform dashboard:
2

Pick a workspace

Choose the workspace whose data the key should reach, using the workspace switcher in the sidebar. The key is scoped to this workspace only.
3

Create a key

Click Create New API Key, name it, and copy the full key including the dot — abc123.xR7mK9pL2qW4....
4

Store it

Save it as an environment variable. The secret is shown once and can’t be recovered after you close the dialog.
Keep your API keys secure and never expose them in client-side code. API keys should only be used in server-side applications.

API Key Format

Tiro API keys follow this format:
{id}.{secret}
For example: abc123.xR7mK9pL2qW4...
PartExampleDescription
Key ID ({id})abc123Visible in Platform dashboard. Used to identify which key is making requests.
Secret ({secret})xR7mK9pL2qW4...Shown only once at creation. The server stores only a hash — it cannot be recovered.
Full API Keyabc123.xR7mK9pL2qW4...The entire string including the dot. This is what you use as the Bearer token.
Common mistake: Do not use just the Key ID (abc123) as your Bearer token. You must use the full key (abc123.xR7mK9pL2qW4...) — the complete string shown when the key was created.

Making Authenticated Requests

Include your API key in the Authorization header of every request:
curl -H "Authorization: Bearer $TIRO_API_KEY" \
     -H "Content-Type: application/json" \
     https://api.tiro.ooo/v1/external/notes
const response = await fetch("https://api.tiro.ooo/v1/external/notes", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.TIRO_API_KEY}`,
    "Content-Type": "application/json",
  },
});

const notes = await response.json();
import os
import requests

headers = {
    'Authorization': f'Bearer {os.getenv("TIRO_API_KEY")}',
    'Content-Type': 'application/json'
}

response = requests.get('https://api.tiro.ooo/v1/external/notes', headers=headers)
notes = response.json()
import (
    "fmt"
    "net/http"
    "os"
)

func makeAuthenticatedRequest() (*http.Response, error) {
    client := &http.Client{}
    req, err := http.NewRequest("GET", "https://api.tiro.ooo/v1/external/notes", nil)
    if err != nil {
        return nil, err
    }
    
    apiKey := os.Getenv("TIRO_API_KEY")
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey))
    req.Header.Set("Content-Type", "application/json")
    
    return client.Do(req)
}
@Service
class TiroApiService {
    
    @Value("\${tiro.api.key}")
    private lateinit var apiKey: String
    
    private val restTemplate = RestTemplate()
    
    fun getNotes(): ResponseEntity<String> {
        val headers = HttpHeaders()
        headers.set("Authorization", "Bearer $apiKey")
        headers.contentType = MediaType.APPLICATION_JSON
        
        val entity = HttpEntity<String>(headers)
        
        return restTemplate.exchange(
            "https://api.tiro.ooo/v1/external/notes",
            HttpMethod.GET,
            entity,
            String::class.java
        )
    }
}

Authentication Errors

If authentication fails, you’ll receive a 401 Unauthorized response. Common reasons include:
  • Missing Authorization header
  • Malformed key (must be {id}.{secret})
  • Unknown key id
  • Inactive, expired, or deleted key
{
  "error": {
    "code": "invalid_api_key",
    "message": "The API key provided is invalid",
    "type": "authentication_error"
  }
}

Legacy personal keys (deprecated)

Before workspaces, a personal API key was tied to your account, not a workspace. Those personal keys are deprecated. Team keys now come through as workspace keys — each team maps to a workspace. Workspace keys replace both.
Legacy personal keys stop working on June 30, 2026. After that, requests made with one return 401 Unauthorized. Migrate before then to avoid downtime.
Legacy personal keyWorkspace key
ScopeAccount-wideOne workspace
Create newDisabledDashboard → pick a workspace → Create New API Key
Existing keysView and revoke only, until June 30, 2026Full lifecycle
Format{id}.{secret}{id}.{secret} — unchanged
The format is identical, so migrating is a one-line swap — no code rewrite.

Migrate in three steps

1

Create a workspace key

In the dashboard, select the workspace that holds the notes your integration uses, then create a key.
2

Swap the secret

Replace the value of your TIRO_API_KEY environment variable with the new key. No other code changes are needed.
3

Revoke the legacy key

Once traffic runs on the new key, delete the legacy key from the Legacy personal keys section of the dashboard.
A legacy key reached every note on your account; a workspace key reaches one workspace. If your data spans several workspaces, create one key per workspace.

Security Best Practices

Environment Variables

Store API keys securely using environment variables:
# .env file (never commit this!)
TIRO_API_KEY=abc123.XYZ...
// Load from environment
const apiKey = process.env.TIRO_API_KEY;
if (!apiKey) {
  throw new Error('TIRO_API_KEY environment variable is required');
}
import os

# Load from environment with validation
api_key = os.getenv('TIRO_API_KEY')
if not api_key:
    raise ValueError('TIRO_API_KEY environment variable is required')
import (
    "fmt"
    "os"
)

func getAPIKey() (string, error) {
    apiKey := os.Getenv("TIRO_API_KEY")
    if apiKey == "" {
        return "", fmt.Errorf("TIRO_API_KEY environment variable is required")
    }
    return apiKey, nil
}
# application.properties
tiro.api.key=${TIRO_API_KEY}

# Or application.yml
tiro:
  api:
    key: ${TIRO_API_KEY}

Additional Security Guidelines

  • Rotate keys regularly: Delete unused keys and generate new ones
  • Separate keys per environment: Use different keys for development and production
  • Monitor usage: Track API key usage and rotate on anomalies
  • Never log API keys: Ensure keys don’t appear in application logs
  • Use HTTPS only: Always make requests over secure connections