Skip to content

Errors & Rate Limits ​

Error format ​

Every error response has this shape:

json
{
  "error": {
    "code": "NOT_FRIENDS",
    "message": "You can only message friends.",
    "details": { "userId": "01JC…" },
    "requestId": "req_7f3a9c"
  }
}

Use code in your app logic. message is for developers, not for end users. Include requestId when you report a problem to us.

Error codes ​

HTTPcodeMeaningTypical app behaviour
400VALIDATION_FAILEDInvalid body or query. details.fields lists each problem.Show field errors. Do not retry.
401CLIENT_KEY_INVALIDMissing or unknown X-Client-Key.Configuration bug.
401UNAUTHENTICATEDAccess token missing, invalid, or expired.Refresh token once, then retry.
401OTP_INVALIDWrong or expired code."Wrong code, try again."
403FORBIDDENNot allowed (for example, non-admin edits a group).Hide the action.
403PROFILE_INCOMPLETEProfile setup not finished.Show profile setup.
403NOT_FRIENDSDirect chat with someone who is not (or no longer) a friend.Mark message failed. Explain.
404NOT_FOUND, USER_NOT_FOUND, CONVERSATION_NOT_FOUND, MESSAGE_NOT_FOUND, FRIEND_REQUEST_NOT_FOUNDMissing or not visible to the caller.Remove from local store if appropriate.
409USERNAME_TAKENUsername already used.Show inline error.
409ALREADY_FRIENDSFriend request to an existing friend.Refresh friendship state.
409FRIEND_REQUEST_EXISTSA pending request already exists from the caller.Refresh friendship state.
409CONFLICTOther state conflict.Refresh, then let the user retry.
413PAYLOAD_TOO_LARGEMedia exceeds the size limit.Ask for a smaller file.
422EDIT_WINDOW_EXPIREDEdit or delete-for-everyone too late.Hide the action after the window.
429RATE_LIMITEDToo many requests. Retry-After header in seconds.Wait and retry.
500INTERNALServer error.Retry with backoff.
503UNAVAILABLETemporary outage or deploy.Retry with backoff.

Retry rule: retry automatically on network errors, 429, 500, and 503. Never retry other 4xx without a change.

Rate limits ​

Limits are per workspace user unless noted. Every response includes:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1792723340
ScopeLimit
POST /auth/otp3 per phone per 10 minutes
POST /auth/verify5 attempts per phone per 10 minutes
Message send (WebSocket + REST, combined)30 per 10 seconds
typing.start1 per second per conversation
GET /users/search30 per minute
POST /friend-requests30 per hour
/developer/*120 per minute per workspace
Everything else300 per minute

WebSocket frames over a limit get an error reply with code RATE_LIMITED and details.retryAfter in seconds. Repeated abuse closes the socket with code 4008.

Questions? Reply to your invitation email.