Overview:
This guide will walk you through how to use Float's API to import logged time data from a CSV file. This is helpful if you're transitioning from another tool, syncing with offline data, or migrating from manual tracking systems.
While technical expertise isn't needed for following the steps below, it is helpful. This guide covers everything from installing Python to running your first API-powered script.
Step 1: Install Python
Python is a programming language we will use to run the import script.
Click the yellow "Download Python" button for your operating system.
Run the installer:
Windows: During installation, make sure to check "Add Python to PATH".
Mac: Use the
.pkg
installer provided.
Once installed, open your terminal:
Windows: Open "Command Prompt" or "Windows Terminal"
Mac: Use the built-in "Terminal" app
Verify Python is installed by running:
python3 --version
You should see a version number like
Python 3.12.0
Step 2: Install Required Python Libraries
We need two libraries: pandas
for reading CSV files and requests
for sending data to the Float API.
In your terminal, run:
pip3 install pandas requests
Step 3: Prepare Your CSV File
Create a CSV file with the following headers:
people_id,project_id,hours,date,task_name
Each row should represent a time entry, for example:
12345,67890,1.5,2025-07-09,Client Meeting
23456,67890,0.75,2025-07-10,Design Review
Save the file as something like time_entries.csv
.
Step 4: Get Your Float API Key
Log in to your Float account as the account owner. Only the account owner can access the API key.
Go to Team Settings > Integrations
Copy the API Key.
Keep this key secret!
You can explore Float's full API documentation here: https://developer.float.com/
Step 5: Copy and Configure the Script
Open any text editor (like Notepad, VS Code, or TextEdit) and paste the following script:
import pandas as pd
import requests
import time
import os
# === CONFIGURATION ===
CSV_FILE = "/mnt/data/testAPIscript.csv"
FLOAT_API_URL = "https://api.float.com/v3/logged-time"
BEARER_TOKEN = "your_float_api_key_here" # β Replace with your actual API key
DRY_RUN = True # Set to False to actually send data to Float
REQUIRED_COLUMNS = {"people_id", "project_id", "hours", "date", "task_name"}
SUCCESS_LOG = "success.log"
ERROR_LOG = "error.log"
# === HEADERS FOR AUTH ===
headers = {
"Authorization": f"Bearer {BEARER_TOKEN}",
"Content-Type": "application/json",
"User-Agent": "Glenn's People Import Integration (glenn@example.com)"
}
# === Clear previous logs ===
for log_file in [SUCCESS_LOG, ERROR_LOG]:
if os.path.exists(log_file):
os.remove(log_file)
# === DIAGNOSTIC: Column count per line ===
print("π Inspecting column count per line in the CSV...\n")
with open(CSV_FILE) as f:
for i, line in enumerate(f, 1):
print(f"Line {i}: {len(line.strip().split(','))} columns")
# === READ CSV ===
try:
df = pd.read_csv(CSV_FILE)
except Exception as e:
print(f"β Error reading CSV: {e}")
exit(1)
# === VALIDATE HEADER COLUMNS ===
missing_cols = REQUIRED_COLUMNS - set(df.columns)
if missing_cols:
print(f"β Missing required columns: {', '.join(missing_cols)}")
exit(1)
# === SEND DATA ===
for index, row in df.iterrows():
row_num = index + 1
# Skip if any required field is missing
if pd.isnull(row["people_id"]) or pd.isnull(row["project_id"]) or pd.isnull(row["hours"]) or pd.isnull(row["date"]):
with open(ERROR_LOG, "a") as elog:
elog.write(f"[Row {row_num}] Skipped (missing required data): {row.to_dict()}\n")
print(f"β οΈ Row {row_num}: Skipped (missing required data)")
continue
# Ensure task_name is a string, even if missing
task_name = "" if pd.isnull(row.get("task_name")) else str(row["task_name"])
# Prepare payload
payload = {
"people_id": int(row["people_id"]),
"project_id": int(row["project_id"]),
"hours": float(row["hours"]),
"date": str(row["date"]),
"task_name": task_name
}
if DRY_RUN:
print(f"[Dry-run] Row {row_num}: {payload}")
else:
try:
response = requests.post(FLOAT_API_URL, json=payload, headers=headers)
error_text = response.text.strip()
if response.status_code in [200, 201]:
with open(SUCCESS_LOG, "a") as slog:
slog.write(f"[Row {row_num}] Success: {payload}\n")
print(f"β Row {row_num}: Success")
else:
with open(ERROR_LOG, "a") as elog:
elog.write(f"[Row {row_num}] Error {response.status_code}: {error_text} | Payload: {payload}\n")
print(f"β Row {row_num}: API Error {response.status_code} β {error_text}")
except Exception as e:
with open(ERROR_LOG, "a") as elog:
elog.write(f"[Row {row_num}] Exception: {e} | Payload: {payload}\n")
print(f"β Row {row_num}: Exception occurred β {e}")
time.sleep(0.75)
Replace:
your_float_api_key_here
with your real token.your@email.com
with your emailYour Name's Float Import Tool
with your name
Save the file as import_to_float.py
Step 6: Run the Script
In the terminal:
Navigate to the folder containing your files:
cd path/to/your/files
Run the script in dry-run mode first:
python3 import_to_float.py
You will see what would be sent without actually sending anything.
When ready, open the file and change:
DRY_RUN = False
Save and re-run:
python3 import_to_float.py
Note: Make sure to save import_to_float.py in the same directory as your import files or use the full path here
Step 7: Review the Logs
success.log
: shows entries that were successfully sent.error.log
: shows any failed entries and why they failed.
Example:
Need Help?
If you have questions or need help formatting your CSV, please contact our support team. Weβre happy to assist!