Skip to content

Submit Admin Timesheet

This endpoint submits a timesheet on behalf of a user. By default the timecards are approved immediately. Set requireReview to true to send them for review instead.

POST /v1/timesheets/timesheets/submit-admin

Include your API key in the x-api-key header. See Authentication.

timesheets:submit-admin

The request body is not validated against a schema. Send every field marked Required in the shape shown. A missing or malformed field usually causes a 500, not a 400.

FieldTypeRequiredDescription
userIdstringYesUser whose timesheet is submitted. Accepts an external user ID (user-a) or an internal one (tenant-123#user-a).
requireReviewbooleanNoDefaults to false. When false, every timecard is stored as approved immediately and no emails are sent. When true, every timecard is stored as pending and review emails are sent.
timecardsobject[]YesTimecards in the timesheet. Send at least one.

Each timecard has the same shape as in Submit Self Timesheet: projectId, taskId, and data with all seven days from Saturday to Friday. Each day has date (YYYY-MM-DD), hours, and an optional description.

The API takes the timesheet period from the earliest and latest date in the first timecard, and builds the timesheet ID from that period. Use the same seven dates in every timecard.

{
"userId": "user-a",
"requireReview": false,
"timecards": [
{
"projectId": "project-mno123pqr4567890",
"taskId": "task-pqr123stu4567890",
"data": {
"Saturday": { "date": "2022-12-31", "hours": 0, "description": null },
"Sunday": { "date": "2023-01-01", "hours": 0, "description": null },
"Monday": { "date": "2023-01-02", "hours": 8, "description": "Worked on implementation" },
"Tuesday": { "date": "2023-01-03", "hours": 8, "description": "Worked on implementation" },
"Wednesday": { "date": "2023-01-04", "hours": 8, "description": "Worked on implementation" },
"Thursday": { "date": "2023-01-05", "hours": 8, "description": "Worked on implementation" },
"Friday": { "date": "2023-01-06", "hours": 8, "description": "Worked on implementation" }
}
}
]
}
Terminal window
curl -X POST "https://api.crewsum.com/v1/timesheets/timesheets/submit-admin" \
-H "x-api-key: $CREWSUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"userId": "user-a",
"requireReview": false,
"timecards": [
{
"projectId": "project-mno123pqr4567890",
"taskId": "task-pqr123stu4567890",
"data": {
"Saturday": { "date": "2022-12-31", "hours": 0, "description": null },
"Sunday": { "date": "2023-01-01", "hours": 0, "description": null },
"Monday": { "date": "2023-01-02", "hours": 8, "description": "Worked on implementation" },
"Tuesday": { "date": "2023-01-03", "hours": 8, "description": "Worked on implementation" },
"Wednesday": { "date": "2023-01-04", "hours": 8, "description": "Worked on implementation" },
"Thursday": { "date": "2023-01-05", "hours": 8, "description": "Worked on implementation" },
"Friday": { "date": "2023-01-06", "hours": 8, "description": "Worked on implementation" }
}
}
]
}'

On success, the API returns HTTP 200 OK. The response does not include the timesheet ID. It is <tenantId>#<userId>#<periodStart>_<periodEnd>, here tenant-123#user-a#20221231_20230106.

Example Response: requireReview is false or omitted

Section titled “Example Response: requireReview is false or omitted”
{
"message": "Successfully submitted timesheet"
}

data has one item for each email the API tried to send. status is fulfilled or rejected. A rejected item also has a rejectionReason.

{
"message": "Successfully submitted timesheet and sent mail messages",
"data": [
{
"to": "manager@example.com",
"status": "fulfilled"
}
]
}
  • requireReview is false or omitted: every timecard is stored as approved. Nobody reviews the time and no emails are sent.
  • requireReview is true: every timecard is stored as pending, and the API sends the same emails as Submit Self Timesheet.
  • Existing timesheet: if a timesheet with the same ID exists, the API overwrites it, even if it was already submitted or approved. There is no “already submitted” check. Timecards that are new in the request are added, timecards left out of the request are removed, and changed timecards are updated. Then every timecard is set to approved or pending according to requireReview, submittedAt is set to the current time, and resubmissionAllowed is set to false.
  • The API returns 400 if the hours on any one date add up to more than 24 across all timecards.
  • The timesheet is saved before the emails are sent. If the email step fails, the API returns 500, but the submission is kept.
StatusMeaning
400userId is missing. Message: UserID Missing.
400One date has more than 24 hours in total. Message: Error submitting timesheet. Daily hours cannot exceed 24 hours on <date>.
500timecards is empty, or a date in the first timecard is not valid. Message: Error parsing timesheet.
500The user could not be found or loaded. Message: Error fetching startup information for the submission.
500Crewsum could not save the timesheet. The message starts with Error saving timesheet. or Error submitting timesheet. and names the step that failed.
500requireReview is true, the timesheet was saved, but the emails could not be prepared. Message: Error sending submission notifications.
500The body is missing or has the wrong shape, for example no timecards array. The response has a generic error body.

Authentication and scope failures are described in Errors.

This endpoint does not trigger a webhook. It does not send timesheet.submitted.