Create Association
This endpoint creates an association between a project and a contact.
Endpoint
Section titled “Endpoint”POST /v1/associations/associationsAuthentication
Section titled “Authentication”Include your API key in the x-api-key header. See Authentication.
Required Scope
Section titled “Required Scope”associations:writeRequest Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
projectId | string | Yes | Project ID to associate. |
contactId | string | Yes | Contact ID to associate. |
contactType | "MANAGER" | "BACKUP_MANAGER" | "ADDITIONAL_CONTACT" | No | Contact role for the project. Defaults to MANAGER. |
notificationLevel | "NONE" | "COPY_ONLY" | "COPY_WITH_LINK" | No | Notification level for this association. Defaults to NONE. |
outstandingTimecardsAction | "SEND" | "NO_SEND" | No | How to handle the project’s pending timecards when the API returns 409. See Outstanding timecards. |
The API does not check contactType and notificationLevel against the allowed values. Other strings are stored as sent, so send only the values listed above.
Example Request Body
Section titled “Example Request Body”{ "projectId": "project-mno123pqr4567890", "contactId": "contact-jkl123mno4567890", "contactType": "MANAGER", "notificationLevel": "COPY_ONLY"}Example Request
Section titled “Example Request”curl -X POST "https://api.crewsum.com/v1/associations/associations" \ -H "x-api-key: $CREWSUM_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "projectId": "project-mno123pqr4567890", "contactId": "contact-jkl123mno4567890", "contactType": "MANAGER", "notificationLevel": "COPY_ONLY" }'const response = await fetch( "https://api.crewsum.com/v1/associations/associations", { method: "POST", headers: { "x-api-key": process.env.CREWSUM_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ projectId: "project-mno123pqr4567890", contactId: "contact-jkl123mno4567890", contactType: "MANAGER", notificationLevel: "COPY_ONLY", }), },);const result = await response.json();POST /v1/associations/associations HTTP/1.1Host: api.crewsum.comx-api-key: <your-api-key>Content-Type: application/json
{ "projectId": "project-mno123pqr4567890", "contactId": "contact-jkl123mno4567890", "contactType": "MANAGER", "notificationLevel": "COPY_ONLY"}Response
Section titled “Response”On success, the API returns HTTP 200 OK. This endpoint does not return 201.
Example Response
Section titled “Example Response”{ "message": "Successfully associated project-mno123pqr4567890 to contact-jkl123mno4567890"}Behavior
Section titled “Behavior”- The project and the contact must both exist in your account and must not be deleted.
- A contact that belongs to a client can be associated only with that client’s projects. A contact with no client can be associated with any project.
- A project and contact can have only one association. To change an existing association, use Update Association.
- After the association is created, Crewsum emits the
associations.createdwebhook event. A webhook delivery failure does not change the API response.
Outstanding timecards
Section titled “Outstanding timecards”The API checks for pending timecards only when all of these are true:
notificationLevelisCOPY_WITH_LINK.- The project has no other association with
COPY_WITH_LINK. - The project has timecards with a pending status.
If you did not send outstandingTimecardsAction, the API returns 409 and does not create the association. The response body is {"message": "Outstanding timesheets for project found", "data": {"timecards": [...]}}. Each item in timecards describes one pending timecard, with fields such as timesheetId, projectId, taskId, status, userId, userFullName, projectName, and taskName.
Send the request again with outstandingTimecardsAction:
SEND: Crewsum emails the pending timecards to the contact with a link to review them, then creates the association. The emails are sent before the association is created. If the create then fails with400or500, the emails have already been sent.NO_SEND: Crewsum creates the association without sending emails.
When the check does not apply, the API ignores outstandingTimecardsAction.
Error Responses
Section titled “Error Responses”| Status | Meaning |
|---|---|
400 | Project or contact not found for association: the project or the contact does not exist in your account, or is deleted. |
400 | Cannot associate contact from another client with project: the contact belongs to a different client than the project. |
409 | The project has pending timecards, and the request did not include outstandingTimecardsAction. See Outstanding timecards. |
500 | Crewsum could not create the association. The message is Error associating <projectId> to <contactId>. This includes an association that already exists for the same project and contact, and a failure to send the timecard emails. |
500 | With outstandingTimecardsAction: "SEND", Crewsum could not load the contact or the account details. The message is Could not get contact for sending timecards or Could not get tenant prefs for sending timecards. |
Authentication and scope failures are described in Errors.