Imported from jeremylongshore/tons-of-skills-marketplace (
skills/.curated/clari-hello-world/SKILL.md). Install upstream withnpx skills add jeremylongshore/tons-of-skills-marketplace --skill clari-hello-world. Copyright stays with the author (MIT).
Clari Hello World
Overview
First API calls against Clari: list available forecasts, export a forecast snapshot, and check export job status. The Clari Export API is the primary integration point for getting forecast, quota, and CRM data out of Clari.
Prerequisites
- Completed
clari-install-authsetup CLARI_API_KEYenvironment variable set- At least one forecast configured in Clari
Instructions
Step 1: List Available Forecasts
curl -s -H "apikey: ${CLARI_API_KEY}" \
https://api.clari.com/v4/export/forecast/list \
| jq '.forecasts[] | {forecastName, forecastId, timePeriods}'
Step 2: Export a Forecast
import requests
import json
import os
import time
api_key = os.environ["CLARI_API_KEY"]
headers = {"apikey": api_key, "Content-Type": "text/plain"}
# Replace with your forecast name from Step 1
forecast_name = "company_forecast"
payload = json.dumps({
"timePeriod": "2026_Q1",
"typesToExport": [
"forecast",
"quota",
"forecast_updated",
"adjustment",
"crm_total",
"crm_closed"
],
"currency": "USD",
"schedule": "NONE",
"includeHistorical": False,
"exportFormat": "JSON"
})
response = requests.post(
f"https://api.clari.com/v4/export/forecast/{forecast_name}",
headers=headers,
data=payload,
)
response.raise_for_status()
job = response.json()
print(f"Export job started: {job['jobId']}")
print(f"Status: {job['status']}")
Step 3: Check Export Job Status
# Poll for job completion
job_id = job["jobId"]
while True:
status_resp = requests.get(
f"https://api.clari.com/v4/export/jobs/{job_id}",
headers={"apikey": api_key},
)
status = status_resp.json()
if status["status"] == "COMPLETED":
print(f"Export ready: {status['downloadUrl']}")
break
elif status["status"] == "FAILED":
print(f"Export failed: {status.get('error', 'Unknown')}")
break
print(f"Status: {status['status']}... waiting 5s")
time.sleep(5)
Step 4: Download and Parse Results
if status["status"] == "COMPLETED":
download = requests.get(status["downloadUrl"])
forecast_data = download.json()
# Print summary
for entry in forecast_data.get("entries", [])[:5]:
print(f" Rep: {entry.get('ownerName')}")
print(f" Forecast: ${entry.get('forecastAmount', 0):,.0f}")
print(f" Quota: ${entry.get('quotaAmount', 0):,.0f}")
print()
Output
The first run returns the authorized forecast list, job status, and a bounded summary needed to confirm connectivity. Treat the downloaded payload as sensitive revenue data: do not print or persist rep-level calls, quota, adjustments, or CRM totals outside an approved storage boundary.
Examples
Use a staging token to list forecast names, submit one read-only export for an approved test period, and log only the job ID, terminal status, and aggregate entry count. If the job does not complete or the period is not expected, stop the walkthrough and investigate through the bounded rate-limit or diagnostic workflow rather than downloading more data.
Error Handling
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized |
Bad API key | Regenerate token in Clari settings |
| No forecasts listed | Wrong org or no forecasts configured | Contact Clari admin |
Job stays PENDING |
Large export | Wait longer, check job status endpoint |
404 on forecast name |
Name mismatch | Use exact name from list endpoint |
Resources
Next Steps
Proceed to clari-local-dev-loop for development workflow setup.