How-To: Upload Data via API

Objective: Upload data files to TBM Studio tables programmatically

Time estimate: 10-20 minutes per integration

When to use: Automating monthly data loads, integrating with ETL pipelines, or uploading from systems where DataLink agents cannot be installed.

Prerequisites

  • Valid authentication token and environment ID (see Authenticate with the API)
  • Upload permissions assigned to your API account
  • Data file in supported format (CSV, TSV, CSV.GZ, or TSV.GZ)

API URL Structure

https://[customerid].apptio.com/biit/api/v1/[domain]/[project]/[table]/[time-period]/[action]

URL Parameters:

Parameter Required Description
customerid Yes Your Apptio customer ID (e.g., acme)
domain Yes Your customer domain (e.g., acme.com)
project Yes Target project name (URL-encoded if contains spaces)
table Yes Target table name (URL-encoded if contains spaces)
time-period Yes Apptio date format (e.g., January:2024) or current
action No append or overwrite (defaults to overwrite)

Additional Parameters:

Parameter Values Description
force true/false Override data validation checks. Cannot combine with action in URL—use POST body instead.

Steps

Step 1: Prepare your data file

  • Ensure data is in CSV or TSV format
  • Column headers should match the target table schema
  • For large files, compress using gzip (.csv.gz or .tsv.gz)

Step 2: Upload the file

cURL:
curl -X POST "https://customer.apptio.com/biit/api/v1/customer.com/Cost%20Transparency/GL%20Data/January:2024/overwrite" \
 -H "apptio-opentoken: YOUR_TOKEN" \
 -H "apptio-current-environment: YOUR_ENV_ID" \
 -H "app-type: Flagship" \
 -H "app-version: NA" \
 -F "myfile=@/path/to/data.csv"
Python:
import requests
import urllib.parse
 
def upload_data(token, env_id, customer_id, domain, project, table, 
 time_period, file_path, action="overwrite"):
 """
 Upload data to TBM Studio via API.
 
 Args:
 token: Authentication token from login
 env_id: Environment ID
 customer_id: Your Apptio customer ID
 domain: Your domain (e.g., 'customer.com')
 project: Target project name
 table: Target table name
 time_period: Time period (e.g., 'January:2024' or 'current')
 file_path: Path to the data file
 action: 'append' or 'overwrite' (default: 'overwrite')
 
 Returns:
 dict: Response containing md5, length, and fileName
 """
 # URL-encode project and table names
 project_encoded = urllib.parse.quote(project)
 table_encoded = urllib.parse.quote(table)
 
 url = (f"https://{customer_id}.apptio.com/biit/api/v1/"
 f"{domain}/{project_encoded}/{table_encoded}/"
 f"{time_period}/{action}")
 
 headers = {
 "apptio-opentoken": token,
 "apptio-current-environment": str(env_id),
 "app-type": "Flagship",
 "app-version": "NA"
 }
 
 with open(file_path, 'rb') as f:
 files = {'myfile': f}
 response = requests.post(url, headers=headers, files=files)
 
 response.raise_for_status()
 return response.json()
 
# Usage example
result = upload_data(
 token=token,
 env_id=env_id,
 customer_id="acme",
 domain="acme.com",
 project="Cost Transparency",
 table="GL Data",
 time_period="January:2024",
 file_path="/path/to/gl_data.csv"
)
print(f"Upload complete: {result['fileName']}, {result['length']} bytes")

Expected Results

A successful upload returns a JSON response:
{
 "md5": "3727119d89edcdd71377e39e18f3a5e1",
 "length": 13,
 "fileName": "data.csv"
}

After upload, the Data > Overview tab in TBM Studio displays "API Data" in the Source field.

Using Append vs. Overwrite

Action Behavior Use Case
overwrite Replaces all existing data in the target time period Monthly full data refresh
append Adds data to existing records Incremental updates, adding new records
Tip: To use both action and force parameters, include them in the POST body as form fields instead of the URL: --form "action=append" --form "force=true"

Common Pitfalls

  • URL encoding: Project and table names with spaces must be URL-encoded (spaces become %20 or +).
  • Date format: Use the exact format Month:Year (e.g., January:2024). "current" uses the current calendar month.
  • MIME type: The only supported MIME type is multipart/form-data.
  • Table creation: If the target table doesn't exist, the API creates it in the first time period of the project, with data appearing in the specified period.