Run a performance review cycle
Submit manager reviews programmatically and reuse review templates across teams. This recipe covers performance "boosts" and presets.
Submit performance boosts
POST /api/v1/performance-boosts
A boost is a manager's review of a direct report. Send a single object or an array of up to 200. Each is processed independently, so the response is an array of per-item results.
Rules
reviewer_emailmust be the direct manager ofemployee_email.- Both people must belong to your company.
supporting_examplesis required for goal performance and culture contribution.- A member can't be reviewed again until their review cycle resets.
Ratings
| Section | rating values |
|---|---|
goal_performance |
exceeded_goals, met_goals, partially_met_goals, did_not_meet_goals |
culture_contribution |
significantly, consistently, somewhat, rarely |
Request
{
"employee_email": "jordan@acme.com",
"reviewer_email": "lee@acme.com",
"review_date": "2026-06-01",
"assessment_data": {
"goal_performance": {
"rating": "met_goals",
"supporting_examples": "Hit all three OKRs and unblocked the launch."
},
"culture_contribution": {
"rating": "consistently",
"supporting_examples": "Mentored two teammates and ran the design crit."
},
"future_development": {
"goals_targets_outcomes": "Lead the mobile redesign next quarter.",
"skill_recommendations": "Stakeholder management"
}
}
}
future_development is optional.
Make the call
curl -X POST "https://api.happily.ai/prod/api/v1/performance-boosts" \
-H "x-api-key: $HAPPILY_API_KEY" \
-H "Content-Type: application/json" \
-d '[{
"employee_email": "jordan@acme.com",
"reviewer_email": "lee@acme.com",
"review_date": "2026-06-01",
"assessment_data": {
"goal_performance": { "rating": "met_goals", "supporting_examples": "Hit all three OKRs." },
"culture_contribution": { "rating": "consistently", "supporting_examples": "Mentored two teammates." }
}
}]'
const boosts = [
{
employee_email: "jordan@acme.com",
reviewer_email: "lee@acme.com",
review_date: "2026-06-01",
assessment_data: {
goal_performance: { rating: "met_goals", supporting_examples: "Hit all three OKRs." },
culture_contribution: { rating: "consistently", supporting_examples: "Mentored two teammates." },
},
},
];
const res = await fetch("https://api.happily.ai/prod/api/v1/performance-boosts", {
method: "POST",
headers: { "x-api-key": process.env.HAPPILY_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify(boosts),
});
const { body: results } = await res.json();
for (const r of results) {
if (r.success) console.log("OK", r.employee_email);
else console.warn("FAILED", r.error_code, r.error);
}
import os, requests
boosts = [{
"employee_email": "jordan@acme.com",
"reviewer_email": "lee@acme.com",
"review_date": "2026-06-01",
"assessment_data": {
"goal_performance": {"rating": "met_goals", "supporting_examples": "Hit all three OKRs."},
"culture_contribution": {"rating": "consistently", "supporting_examples": "Mentored two teammates."},
},
}]
res = requests.post(
"https://api.happily.ai/prod/api/v1/performance-boosts",
headers={"x-api-key": os.environ["HAPPILY_API_KEY"]},
json=boosts,
)
for r in res.json()["body"]:
print("OK" if r.get("success") else f"FAILED {r.get('error_code')}", r)
Response
{
"statusCode": 200,
"body": [
{ "success": true, "employee_email": "jordan@acme.com", "reviewer_email": "lee@acme.com", "review_date": "2026-06-01" }
]
}
A 200 does not mean every boost succeeded. Each item in body is independent. Check success, and on failure read error_code and error. See the error codes.
Save a review preset
POST /api/v1/performance-preset
A preset is a reusable review template assigned to teams or members. Provide either teams (internal team IDs, max 50) or members (emails, max 50).
curl -X POST "https://api.happily.ai/prod/api/v1/performance-preset" \
-H "x-api-key: $HAPPILY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q3 Engineering Review",
"goals_feedback": "Reflect on your top goal this quarter.",
"culture_contribution": "How did you live our values?",
"next_review": "2026-09-01",
"teams": ["t123456789"]
}'
import os, requests
res = requests.post(
"https://api.happily.ai/prod/api/v1/performance-preset",
headers={"x-api-key": os.environ["HAPPILY_API_KEY"]},
json={
"name": "Q3 Engineering Review",
"goals_feedback": "Reflect on your top goal this quarter.",
"culture_contribution": "How did you live our values?",
"next_review": "2026-09-01",
"teams": ["t123456789"],
},
)
print(res.json()["data"]["_id"])
Each team or member belongs to a single preset. When you assign a team or member to a new preset, they are removed from any preset that previously covered them.
Read existing feedback
GET /1/performance_feedback?email=jordan@acme.com&reviewer_email=lee@acme.com
Provide email (the employee), reviewer_email (the reviewer), or both. The response contains a feedback array with score and comment, plus a pagination object.
Get an API key