Skip to main content

Documentation Index

Fetch the complete documentation index at: https://api-docs.tiro.ooo/llms.txt

Use this file to discover all available pages before exploring further.

Idempotency

Use the event id and resource resourceId for idempotent processing:
const processedEvents = new Set();

function processEvent(event) {
  // Deduplicate by event ID
  if (processedEvents.has(event.id)) {
    return;
  }

  // Process the event
  handleEvent(event);
  processedEvents.add(event.id);
}

Error Handling

Always return appropriate HTTP status codes:
app.post('/webhooks/tiro', (req, res) => {
  try {
    const event = req.body;
    
    // Process the event
    processEvent(event);
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).send('Internal server error');
  }
});

Retry Handling

Our webhook system will retry failed deliveries. Handle retries gracefully:
  • Return 2xx status codes for successful processing
  • Return 4xx status codes for permanent failures (we won’t retry)
  • Return 5xx status codes for temporary failures (we will retry)

Security

Always verify webhook authenticity:
function verifyWebhookAuth(authHeader, expectedSecret) {
  const token = authHeader.replace('Bearer ', '');
  return token === expectedSecret;
}

app.post('/webhooks/tiro', (req, res) => {
  const authHeader = req.headers.authorization;
  
  if (!verifyWebhookAuth(authHeader, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Unauthorized');
  }
  
  // Process webhook event
  processEvent(req.body);
  res.status(200).send('OK');
});

Resource Routing

Use resourceType and resourceId for efficient routing:
function routeEvent(event) {
  const { resourceType, resourceId } = event.data;

  switch (resourceType) {
    case 'Note':
      return handleNoteEvent(event.type, resourceId, event.data.resource);
    case 'NoteDocument':
      return handleNoteDocumentEvent(event.type, resourceId, event.data.resource);
    case 'NoteSummary':
      return handleNoteSummaryEvent(event.type, resourceId, event.data.resource);
    case 'FolderNoteRelation':
      return handleFolderNoteEvent(event.type, resourceId, event.data.resource);
    default:
      console.log('Unknown resource type:', resourceType);
  }
}