Errors

A request that fails returns a 4xx or 5xx status and a JSON body with a single error object. The object always has a code your program can branch on and a message a person can read.

This page lists the codes any request can return. Each operation lists the other codes it can return in its own Errors block.

#Error responses

Every error body has the same shape, described in full as the error object:

  • error.code is always present. It is a stable, lowercase identifier such as record_not_found. Codes don’t change once published.
  • error.message is always present. It is English you can show to a person as it is. Messages may be reworded, so don’t match on them.
  • error.fields appears only when the failure is tied to particular fields. It maps each field to its own code and message; see Field errors.

The same code always comes with the same HTTP status.

post/deals
curl https://api.carom.io/deals \
  -H "Authorization: Bearer $CAROM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deal": {
      "pipeline_id": "3d9e1b7a-5c2f-4a8d-b6e0-7f1c4a9d2e58",
      "contact_id": "1f3c9a52-7b0e-4d4a-9c1e-2a6f0d8b3e41",
      "amount": -500
    }
  }'
Response400
{
  "error": {
    "code": "invalid_request",
    "message": "Please provide the required parameters for this endpoint.",
    "fields": {
      "name": {
        "code": "required",
        "message": "Is missing"
      },
      "amount": {
        "code": "invalid",
        "message": "Must be greater than or equal to 0"
      }
    }
  }
}

#HTTP statuses

Success

200The request succeeded. The body holds the record or result. Operations that return an existing record when one already matches, such as Create an organization, answer 200 whether or not they created one.
201A record was created. The body holds the new record.
202Carom accepted the request and started work that finishes later, such as generating a briefing or an answer. The operation’s page says how to get the result.
204The request succeeded and there is no body. Most deletes answer 204.

Failure

400The request is malformed or a parameter failed validation.
401The API key is missing or no longer valid. See Authentication.
403The key or your key’s user isn’t allowed to do this: the key’s tier, the account’s API access setting, the user’s permissions, or terms the user hasn’t accepted.
404The record doesn’t exist or isn’t visible to your key, the id isn’t a valid UUID, or no operation exists at that path.
405The path doesn’t accept that HTTP method.
406The Accept header excludes application/json.
409The request conflicts with the record’s current state, for example a proposal that has already been answered or a tag name that is already taken.
413The request body, or a file the request asks for, is too large.
415The request’s Content-Type header names a type other than application/json.
422The request is well formed, but the record’s state doesn’t allow it, for example deleting a pipeline that still has deals.
429Too many requests. Wait the number of seconds in the Retry-After header before trying again. See Rate limits.
500Something failed inside Carom.
502A service Carom depends on, such as file storage, billing, or its job queue, failed.

#Codes any request can return

Resource pages leave these out of their Errors blocks. Some, such as record_not_found, also appear there when an operation gives them a specific cause.

Codes

  • 400invalid_requestA parameter is missing, malformed, or out of range, or a body key names a path parameter with a different value. error.fields names each one.
  • 401unauthorizedNo API key was sent, or the key is unknown, revoked, or expired, or its user or account no longer has access.
  • 403api_key_insufficientThe operation needs a read/write key, or accepts no API key at all.
  • 403api_access_disabledAn admin has turned API access off for the account. See Account API access.
  • 403api_access_read_onlyA read/write key called a Write key operation while the account’s API access is read-only.
  • 403terms_acceptance_requiredYour key’s user must sign in to the app and accept Carom’s current terms.
  • 403permission_deniedYour key’s user can see the record but isn’t allowed to do this to it.
  • 404record_not_foundNo record with that id exists, it isn’t visible to your key, or the id isn’t a valid UUID. The cases return the same response.
  • 406not_acceptableThe Accept header doesn’t allow application/json. Send Accept: application/json, or leave the header out.
  • 415unsupported_media_typeThe Content-Type header names a type other than application/json. Send the body as JSON, or leave the header out on a request without a body.
  • 429rate_limitedToo many requests. The Retry-After header gives the seconds to wait.
  • 500errorAn unexpected failure inside Carom. The request may succeed if you try again later.

Rate limits. Each API key can make 600 requests a minute; each key has its own limit. Over it, requests get 429 rate_limited, and the Retry-After header gives the number of seconds to wait. Some operations that start AI work, such as sending a message to Ask Carom and generating a meeting brief, have lower limits of their own, so handle 429 rate_limited on any request.

A few operations report a 500 with a more specific code than error. Handle every 500 the same way.

#Other shared codes

These codes come from several resources or from the API as a whole. Resource pages list them where they apply.

Codes

  • 400invalid_cursorThe cursor is unreadable, or came from another list or sort. Request the first page again. See Cursor pagination.
  • 400unsupported_cursor_directionYou sent prev_cursor to a list that pages forward only. See Paging backward.
  • 404not_foundNo operation exists at that path.
  • 404no_transcriptThe meeting is visible to your key but has no transcript. See Retrieve a transcript.
  • 405method_not_allowedThe path exists but doesn’t accept that HTTP method.
  • 409idempotency_key_in_useAn earlier request with the same Idempotency-Key is still running. Retry shortly. See Handling errors.
  • 409tag_name_takenAnother tag in the account already has that name. error.fields.name.code is taken. See Tags.
  • 413payload_too_largeThe request body is larger than 5 MB.
  • 502rejectedCarom couldn’t queue work the request needed. Try again later.
  • 502billing_unavailableRetrieve an account couldn’t read the account’s billing details. Try again later.

A record named in the request that doesn’t exist or isn’t visible to your key always returns 404 record_not_found, whatever kind of record it is.

#Field errors

When a request fails because of particular fields, error.fields maps each field to an object with its own code and message. Each field reports only its first problem.

Field names are the parameter names you sent, without the resource wrapper: a bad name inside {"deal": {…}} is reported as name, not deal.name. Deeper fields, and bodies with more than one nested object, use dotted paths in the form parent.child. An entry in an array is named by its index, as in employments.0.organization.id.

A body key can’t name a different record from the path. If a top-level body key has the name of a path parameter, such as id in PATCH /contacts/{id}, and a different value, the request fails with 400 invalid_request and that key’s field code is not_allowed. The same value is accepted.

Field codes come from a small fixed set, so you can mark the input and show the message without special cases.

Field codes

  • required

    The field is missing or empty.

  • invalid_format

    The value isn’t in the expected format, such as a malformed UUID, date, or email address.

  • too_long

    The value is longer than allowed.

  • too_short

    The value is shorter than allowed.

  • taken

    The value is already in use.

  • not_allowed

    The field can’t be set in this request, for example a body key that names a path parameter with a different value.

  • invalid

    The value isn’t valid for another reason. The message says why.

#Handling errors

  • Branch on error.code, not on the status or the message. Several codes share a status.
  • Don’t retry a 4xx unchanged. Fix the request, the key, or the record’s state first. The exception is 429: wait the number of seconds in the Retry-After header, then try again. On 400 invalid_cursor, start the list again from the first page.
  • Retry a 5xx later. 500 and 502 responses, including 502 rejected and 502 billing_unavailable, describe failures on Carom’s side or at a service it depends on. Wait before retrying, and wait longer after each failure.
  • Know which requests are safe to retry. GET and PATCH are safe to retry. A retried DELETE returns 404 record_not_found if the first attempt deleted the record, so treat that 404 as success. Create a group, Create a milestone, Create a pipeline, and Create a space accept an Idempotency-Key header of 1 to 255 printable ASCII characters. For 24 hours after a successful create, a request from the same user to the same path with the same key returns the first response without creating another record, whatever its body. While the first request is still running, the retry gets 409 idempotency_key_in_use. Before retrying any other POST that creates a record, check whether the first attempt created it.
  • Treat 404 as “not visible”. A record your key can’t see answers the same way as one that doesn’t exist.