Errors
Every failure has the same shape: an HTTP status, and an error object with a stable code and a
message that says how to fix it.
Code
Branch on code, never on message. We improve the wording of messages all the time. details
is there when it helps: the fields that failed validation, the stage requirements a deal does not
meet yet, or the limit that refused a key.
Each endpoint in the API reference lists the codes it can return. The tables below are the ones you will meet most.
Codes you will see everywhere
| Status | Code | What happened |
|---|---|---|
400 | VALIDATION_ERROR | The body or a query parameter is not valid. details.fieldErrors names each field, and message says the fix. |
400 | MALFORMED_JSON | The body is not valid JSON. |
400 | BAD_REQUEST | An id in the path is not a valid id. |
401 | UNAUTHORIZED | The key is missing, malformed, or revoked, or its broker is deactivated. See Authentication. |
403 | READ_ONLY_KEY | The key is read-only, and this is a write. |
403 | KEY_LIMITED | A limit on the key refuses this request. details.limit names it. See Key limits. |
403 | VIEW_ONLY | The key's broker has view-only access, and this is a write. |
403 | SANDBOX_REFUSED | A sandbox cannot do this, such as billing or phone calls. See Sandbox. |
403 | FORBIDDEN | The person your key acts as cannot do this in BrokerPlus either, such as send from the connected mailbox. |
403 | POLICY_BLOCKED | Your brokerage's automation policy does not allow messages to clients to be asked for this way. An admin changes it in BrokerPlus. |
404 | NOT_FOUND | The record does not exist, or your key cannot see it. See below. |
409 | CONFLICT | The record changed while we checked it, or another system controls it. Read it again first. |
409 | APPROVAL_TASK | The task asks the broker to approve a BrokerPlus suggestion. Only the broker decides it, in BrokerPlus. |
409 | NOT_SENT | A request that reaches a client could not go out as it stands, and nothing was sent. message says why. |
410 | CONTACT_MERGED | The contact was merged into another one. details.merged_into_id is the one it became. |
412 | EMAIL_NOT_CONNECTED | The broker has no connected mailbox, so nothing can be emailed as them. |
412 | SMS_NOT_CONNECTED | The broker has no phone number, so nothing can be texted as them. |
413 | FILE_TOO_LARGE | The upload is over the size limit. |
429 | RATE_LIMITED | More than 600 requests in a minute. Wait for Retry-After seconds. |
503 | SERVICE_UNAVAILABLE, TRY_AGAIN | BrokerPlus is briefly busy and did nothing. Wait a moment and send the same request again. |
5xx | INTERNAL_ERROR | Something failed on our side, but a record might already have changed. Check before you retry. |
Codes for one area
| Area | Codes |
|---|---|
| Idempotency and batch | IDEMPOTENCY_KEY_IN_FLIGHT, IDEMPOTENCY_KEY_CLAIMED, IDEMPOTENCY_KEY_REUSED, EXTERNAL_ID_TAKEN, EXTERNAL_ID_IN_FLIGHT. See Idempotency and batch. |
| Change feed | CHECKPOINT_EXPIRED (410): the checkpoint is older than 30 days. See Staying in sync. |
| Contacts | DUPLICATE_CONTACT (you sent check_duplicates: true and the person is in the book), ALREADY_EXISTS, ALREADY_MERGED, MERGE_CONFLICT, CLIENT_DATA_LOCKED, NO_EMAIL_ON_FILE, NO_PHONE_ON_FILE. |
| Deals | INVALID_PARTY, INVALID_BOARD, INVALID_STAGE, INVALID_LENDER, BROKER_HAS_NO_BOARDS, STAGE_REQUIREMENTS_UNMET, DEAL_LOCKED, PARTY_ALREADY_ON_DEAL, HAS_PROFILE, AML_GATE_BLOCKED. |
| Commission | COMMISSION_ACCESS, NO_COMMISSION, COMMISSION_EXISTS, INVALID_BROKER. |
| Tasks | INVALID_DEAL, INVALID_CONTACT, INVALID_ASSIGNEE, NO_TEAM, ALREADY_COMPLETED, ALREADY_CANCELLED, ALREADY_OPEN. |
| Scheduling | SLOT_TAKEN, HOST_DOUBLE_BOOKED, MEETING_TYPE_DISABLED, BOOKING_CANCELED, NOT_A_BOOKING, CONTACT_INCOMPLETE. |
| Conditions | REVIEW_REQUIRED: review the lender email in BrokerPlus before you change the condition. |
| Consents | ALREADY_REVOKED. |
| Suggestions | APPROVE_IN_BROKERPLUS: the suggestion reaches a client, so the broker approves it in BrokerPlus. |
| Sandbox | SANDBOX_ONLY: the endpoint works only with a sandbox key. |
| Other | INVALID_PROVINCE, INVALID_ROLE_LABEL, INVALID_APPROVAL_NUMBER, LIMIT_REACHED. |
The reference entry for each endpoint says what each of these means there.
A 404 doesn't always mean deleted
A record your key cannot see looks exactly like one that does not exist. A record from another
brokerage, from a team the broker is not on, or one that was moved or deleted, all return 404.
That is on purpose: the API never confirms that a record exists to a key that cannot read it.
GET /v1/me tells you which brokerage and broker your key acts as. Start there when a 404
surprises you.
What to retry
| Failure | Retry? |
|---|---|
429 RATE_LIMITED | Yes, after Retry-After seconds. |
503 | Yes, the same request, after a short wait. Back off exponentially if it repeats. |
409 CONFLICT | Read the record again, check the change still makes sense, then send it. |
A timeout, or a 5xx | Check whether the record changed first. A server error does not prove nothing happened. With an Idempotency-Key, resend the same request with the same key. |
Any other 4xx | No. Fix the request, the key, or the data first. Retrying unchanged gets the same answer. |