Skip to main content
Tutorials

Integrate Project into Your App

Connect your Triform Project to external applications via API

Overview

Once you've built and tested a Project in Triform, you'll want to integrate it into your application. This tutorial covers API integration, authentication, and best practices.

Time required: 20-30 minutes

Prerequisites

  • A deployed Triform Project
  • API key for authentication
  • Basic knowledge of HTTP requests

Step 1: Deploy your Project

Before integrating, deploy your Project:

  1. Open your Project on the Canvas

  2. Click Deploy in the Top Bar

  3. Select the target environment (staging or production)

  4. Configure the deployment:

    • Endpoint name: Choose a memorable name (e.g., news-digest)
    • HTTP method: POST (most common) or GET
    • Authentication: API key required (recommended)
  5. Click Deploy Now

  6. Copy the generated endpoint URL:

    https://app.triform.ai/api/in/31460071-17aa-43e8-a0e6-fb22984c0bdc/26420f15-2143-443f-bca9-45c5b0720784

Step 2: Generate an API key

  1. Go to Profile → API Keys
  2. Click Create New Key
  3. Name it: Production Integration
  4. Set permissions: Execute Projects
  5. Copy the key (shown only once!)
  6. Store securely (use environment variables)

Security note: Never commit API keys to version control. Use environment variables or secret managers.

Step 3: Make your first API call

Using cURL

This is an API-call that would trigger a certain flow with the {"sources": ["https://newsapi.org/v2/top-headlines?country=us", "https://api.example.com/tech-news"]} payload:

curl -X POST 'https://app.triform.ai/api/in/31460071-17aa-43e8-a0e6-fb22984c0bdc/26420f15-2143-443f-bca9-45c5b0720784' \  --header 'Authorization: 88ffe8398f972837ccc6e0a6cd31c5c92689040c' \  --header 'Content-Type: application/json' \  --data '{"sources": ["https://newsapi.org/v2/top-headlines?country=us", "https://api.example.com/tech-news"]}'

Using Python

import requestsimport osAPI_KEY = os.environ.get('TRIFORM_API_KEY')ENDPOINT = 'https://app.triform.ai/api/in/31460071-17aa-43e8-a0e6-fb22984c0bdc/26420f15-2143-443f-bca9-45c5b0720784'headers = {    'Authorization': API_KEY,    'Content-Type': 'application/json'}payload = {    'sources': [        'https://newsapi.org/v2/top-headlines?country=us',        'https://api.example.com/tech-news'    ]}response = requests.post(ENDPOINT, json=payload, headers=headers)if response.status_code == 200:    result = response.json()    print('Success:', result)else:    print('Error:', response.status_code, response.text)

Using JavaScript (Node.js)

const axios = require('axios');const API_KEY = process.env.TRIFORM_API_KEY;const ENDPOINT = 'https://app.triform.ai/api/in/31460071-17aa-43e8-a0e6-fb22984c0bdc/26420f15-2143-443f-bca9-45c5b0720784';const headers = {  'Authorization': API_KEY,  'Content-Type': 'application/json'};const payload = {  sources: [    'https://newsapi.org/v2/top-headlines?country=us',    'https://api.example.com/tech-news'  ]};axios.post(ENDPOINT, payload, { headers })  .then(response => {    console.log('Success:', response.data);  })  .catch(error => {    console.error('Error:', error.response?.status, error.response?.data);  });

Using JavaScript (Browser/React)

const callTriformAPI = async () => {  const API_KEY = process.env.REACT_APP_TRIFORM_API_KEY;  const ENDPOINT = 'https://app.triform.ai/api/in/31460071-17aa-43e8-a0e6-fb22984c0bdc/26420f15-2143-443f-bca9-45c5b0720784';    try {    const response = await fetch(ENDPOINT, {      method: 'POST',      headers: {        'Authorization': API_KEY,        'Content-Type': 'application/json'      },      body: JSON.stringify({        sources: [          'https://newsapi.org/v2/top-headlines?country=us',          'https://api.example.com/tech-news'        ]      })    });        if (!response.ok) {      throw new Error(`HTTP error! status: ${response.status}`);    }        const data = await response.json();    console.log('Success:', data);    return data;  } catch (error) {    console.error('Error:', error);  }};

Step 4: Handle responses

Triform API responses follow this structure:

Success response (200 OK)

{  "execution_id": "exec_abc123",  "status": "completed",  "output": {    "digest": "Top stories today include...",    "article_count": 42,    "topics": ["technology", "politics", "science"]  },  "execution_time_ms": 3420,  "timestamp": "2025-10-01T10:30:00Z"}

Error response (4xx/5xx)

{  "error": {    "code": "invalid_input",    "message": "Field 'sources' is required",    "details": {      "field": "sources",      "expected_type": "array"    }  },  "request_id": "req_xyz789"}

Handling in code

def call_triform_api(payload):    response = requests.post(ENDPOINT, json=payload, headers=headers)        if response.status_code == 200:        data = response.json()        return {            'success': True,            'data': data['output'],            'execution_id': data['execution_id']        }    elif response.status_code == 400:        error = response.json()['error']        return {            'success': False,            'error': error['message'],            'code': error['code']        }    elif response.status_code == 429:        # Rate limit exceeded        return {            'success': False,            'error': 'Rate limit exceeded. Try again later.'        }    elif response.status_code >= 500:        # Server error        return {            'success': False,            'error': 'Triform service temporarily unavailable'        }    else:        return {            'success': False,            'error': f'Unexpected error: {response.status_code}'        }

Step 5: Implement error handling

Retry logic with exponential backoff

import timefrom typing import Optionaldef call_with_retry(payload, max_retries=3):    for attempt in range(max_retries):        try:            response = requests.post(                ENDPOINT,                json=payload,                headers=headers,                timeout=30            )                        if response.status_code == 200:                return response.json()            elif response.status_code == 429:                # Rate limited, wait and retry                wait_time = 2 ** attempt  # 1s, 2s, 4s                time.sleep(wait_time)                continue            elif response.status_code >= 500:                # Server error, retry                wait_time = 2 ** attempt                time.sleep(wait_time)                continue            else:                # Client error, don't retry                raise Exception(f"API error: {response.text}")                        except requests.exceptions.Timeout:            if attempt < max_retries - 1:                time.sleep(2 ** attempt)                continue            raise        except requests.exceptions.RequestException as e:            if attempt < max_retries - 1:                time.sleep(2 ** attempt)                continue            raise        raise Exception(f"Failed after {max_retries} attempts")

Timeout handling

Always set timeouts to prevent hanging requests:

# Set reasonable timeout (connect timeout, read timeout)response = requests.post(    ENDPOINT,    json=payload,    headers=headers,    timeout=(5, 30)  # 5s to connect, 30s to read)

Step 6: Integrate into your application

Example: Web dashboard

# Flask appfrom flask import Flask, render_template, request, jsonifyapp = Flask(__name__)@app.route('/dashboard')def dashboard():    return render_template('dashboard.html')@app.route('/api/refresh-news', methods=['POST'])def refresh_news():    sources = request.json.get('sources', [])        result = call_triform_api({        'sources': sources    })        if result['success']:        return jsonify({            'digest': result['data']['digest'],            'article_count': result['data']['article_count']        })    else:        return jsonify({'error': result['error']}), 400

Example: Scheduled job

# Daily cron jobimport scheduleimport timedef fetch_daily_news():    print("Fetching daily news digest...")        payload = {        'sources': [            'https://newsapi.org/v2/top-headlines?country=us',            'https://api.example.com/tech-news'        ]    }        result = call_with_retry(payload)        # Save to database or send email    save_to_database(result['output']['digest'])    send_email_digest(result['output']['digest'])        print("Daily news digest completed")# Schedule for 6 AM dailyschedule.every().day.at("06:00").do(fetch_daily_news)while True:    schedule.run_pending()    time.sleep(60)

Example: Real-time processing

# Process incoming webhooksfrom fastapi import FastAPI, BackgroundTasksapp = FastAPI()@app.post('/webhook/new-content')async def handle_new_content(data: dict, background_tasks: BackgroundTasks):    # Trigger Triform processing in background    background_tasks.add_task(process_with_triform, data)    return {'status': 'processing'}def process_with_triform(data):    result = call_triform_api({        'content': data['content'],        'metadata': data['metadata']    })        # Store results    store_results(result)

Step 7: Monitor and optimize

Track API usage

import logginglogger = logging.getLogger(__name__)def call_triform_api_with_logging(payload):    start_time = time.time()        try:        response = requests.post(ENDPOINT, json=payload, headers=headers)        elapsed = time.time() - start_time                logger.info(f"Triform API call completed in {elapsed:.2f}s, status: {response.status_code}")                return response.json()    except Exception as e:        elapsed = time.time() - start_time        logger.error(f"Triform API call failed after {elapsed:.2f}s: {str(e)}")        raise

Caching results

from functools import lru_cacheimport hashlibimport json# Simple in-memory cachecache = {}CACHE_TTL = 3600  # 1 hourdef get_cache_key(payload):    return hashlib.md5(json.dumps(payload, sort_keys=True).encode()).hexdigest()def call_triform_cached(payload):    cache_key = get_cache_key(payload)        # Check cache    if cache_key in cache:        cached_data, timestamp = cache[cache_key]        if time.time() - timestamp < CACHE_TTL:            logger.info("Returning cached result")            return cached_data        # Call API    result = call_triform_api(payload)        # Store in cache    cache[cache_key] = (result, time.time())        return result

Best practices

Use environment variables — Never hardcode API keys

Implement retries — Network issues happen; retry with backoff

Set timeouts — Don't let requests hang indefinitely

Log everything — Track success/failure for debugging

Cache when appropriate — Save API calls for expensive operations

Monitor quota — Track usage against your plan limits

Test error paths — Ensure your app handles API failures gracefully

Version your integration — Track which API version you're using

Troubleshooting

Problem: 401 UnauthorizedSolution: Check API key is correct and has Execute permissions

Problem: 429 Too Many RequestsSolution: Implement rate limiting, add delays between requests

Problem: 500 Server ErrorSolution: Retry with backoff, check Triform status page

Problem: Slow responsesSolution: Optimize your Project, add caching, use async requests

Problem: Unexpected output formatSolution: Verify Project schema matches your expectations, check docs

Next steps

Continue exploring the documentation to learn about deployments, API key management, monitoring, quotas, and security best practices.