docs field links to the matching section of this page.
parameter, the parameter at fault, and where it helps allowed, the accepted values. Always quote the request_id when you contact support.
Errors of the OpenID Connect endpoints use the OAuth format instead, see OAuth errors.
Overview
Request errors
missing_parameter
400. A required parameter is missing.parameter names it. On Profile it means you did not pass exactly one of username, csid_id or address.
invalid_parameter
400. A parameter has an invalid value, for example an unknownblockchain, a period other than 6h, 1d, 7d or 30d, a limit out of range, an unknown sort, a malformed cursor or a csid_id that is not the sub of a CabalSpy ID token. parameter names it and allowed lists the accepted values where there is a fixed list. On the stream it means an invalid blockchain.
instance_required
400. Your account has several CabalSpy ID instances and the API cannot tell which one you mean. Addinstance=<client_id> to the request. The message lists your instances.
Authentication errors
missing_api_key
401. No API key was sent. Pass it asAuthorization: Bearer <key> or as the apiKey or api_key query parameter. See Authentication.
invalid_api_key
403. The API key is invalid, revoked or does not exist. Copy the key again from the API Dashboard. On the stream this code is also used when no key was sent.product_not_enabled
403. The key is valid for the CabalSpy API but not enabled for CabalSpy ID. Open the API keys page of the dashboard and switch on CabalSpy ID for the key.no_instance
403. Your account has no CabalSpy ID instance yet. Create one in the dashboard on the CabalSpy ID tab.instance_not_found
404. Theinstance you passed is not an active CabalSpy ID instance of your account. Check the Instance ID (csid_...) in the dashboard.
Access errors
scope_not_allowed
403.scope=global, access to every CabalSpy ID user, is available on the Enterprise plan. Without it your key sees the users of your instance. Remove the parameter or contact sales.
plan_user_limit
403. You passed an anonymous id (anon_...). The person signed in beyond your plan’s user limit, so your platform receives no data for them until it upgrades. The error carries "limited": true. See Plans and limits.
profile_not_found
404. No CabalSpy ID user matches the username, csid_id or address, or the user is not visible to your key: they never signed in to your instance, removed access, were blocked by you, or are beyond your plan’s user limit.wallet_not_found
404. The wallet is not verified on this chain by one of your users. Check theblockchain: a wallet is only found on the chains it is verified on, listed in the user’s wallets[].chains. As with profile_not_found, users outside your instance or beyond your plan’s user limit are not visible.
Limits
rate_limit_exceeded
429. You sent more requests per second than your plan allows. The response carriesRetry-After: 1, wait a second and retry. X-RateLimit-Limit shows your limit. See Plans and limits.
Server errors
internal_error
500. Something went wrong on our side. Retry with a backoff, and contact support with therequest_id if it persists.
service_unavailable
503. A data source is temporarily unavailable, currently used by Holdings. Retry shortly.Thesis errors
These codes come from the thesis endpoints of the Data API and from the browser API. Their messages are written for end users, so you can show them as they are.plan_user_limit (above) also applies when a user beyond your plan’s user limit tries to write.
invalid_body
400. The text was rejected: empty, longer than 1,000 characters, more than two links, written in all caps, repeated-character spam, or containing a blocked word. The message says which.duplicate
400. The user posted exactly the same text within the last day.sign_in_required
401. Browser API only: noAuthorization: Bearer <token> was sent. Let the user sign in with CabalSpy ID and pass their access token.
invalid_token
401. Browser API only: the user’s token is invalid or expired, the user revoked access, or the account is not active. Access tokens live 15 minutes, refresh the token or let the user sign in again.scope_missing
403. Browser API only: the access token does not carry the scopethesis. Request thesis at sign-in.
consent_required
403. Data API: the user has not signed in to your app with the scopethesis, revoked it, or is blocked by you. Ask the user to sign in again with the scope. Eligibility returns this as reason instead of an error.
sandbox_user
403. Made-up sandbox test users cannot write theses.not_a_holder
403. Only holders can post a thesis: one of the user’s verified wallets must have bought the token and still hold it. Replies, reactions and reports do not need this.posting_paused
403. The user is paused from posting, replying and reacting, for example after several of their posts were hidden after reports. The message says until when.reporting_paused
403. Moderators rejected too many of the user’s reports, so they cannot report posts for 30 days. The message says until when. See Moderation and appeals.not_found
404. For appeals: there is no such notification for this user, or it cannot be appealed. Otherwise: the thesis or reply does not exist, was hidden or deleted, or the user tried to delete someone else’s post. Replies to a reply are also refused with this code.rate_limited
429. The user writes too fast: 5 theses per hour and 1 per token every 10 minutes, 30 replies per hour, 120 reactions per hour, 20 reports per day. On the browser API also too many requests from one IP address. Different from rate_limit_exceeded, which is about your API key.Stream errors
The trades stream sends errors as a message and then closes the connection with code 4403.plan_required
The live stream is included from the Pro plan. Upgrade at apidashboard.cabalspy.xyz/billing/csid.too_many_connections
Each API key can hold at most 5 stream connections at once, and separately 5 theses stream connections. Close unused connections, or share one connection across your services.too_many_tokens
Theses stream only: a subscribe frame would take the connection above 200 tokens. The frame is ignored and the connection stays open. Unsubscribe from tokens you no longer show, subscribe with"all": true, or open another connection.
invalid_frame
Theses stream only: the frame is not JSON or not a known op. Send{"op": "subscribe", "tokens": [{"blockchain": "solana", "mint": "..."}]}, {"op": "unsubscribe", ...}, {"op": "subscribe", "all": true} or ping. The connection stays open.
