This guide explains how to use the Float API to import log time entries from a CSV file. Use this process when you are migrating from another tool, syncing offline data, or moving from manual tracking.
π Note: You do not need to be a developer to follow this guide, but basic terminal familiarity helps. This article walks through installing Python, preparing your CSV, configuring the script, and running a dry run before sending data.
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 team's 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 atΒ 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 more help?
If you have questions or need help formatting your CSV, contact our support team. We are happy to assist!