Documentation Index
Fetch the complete documentation index at: https://mintlify.com/pacifica-fi/docs-migrate/llms.txt
Use this file to discover all available pages before exploring further.
Pacifica’s API uses standard HTTP status codes for REST responses and a parallel numeric code system for WebSocket action results. Understanding the distinction between transport-level errors (HTTP status) and business-logic errors (422 with a code in the body) is the key to writing robust error-handling code.
When you receive a 422 Unprocessable Entity, always inspect the response body for the code field. That integer value tells you exactly which business rule was violated — far more precisely than the HTTP status alone.
HTTP Status Codes
These codes appear on every REST response. A 2xx response means the request was accepted and processed successfully.
| Code | Status | Meaning |
|---|
400 | Bad Request | The request body is malformed, a required field is missing, or the signature is invalid. |
403 | Forbidden | Access denied — typically because the request originates from a restricted region. |
404 | Not Found | The requested resource or endpoint does not exist. |
409 | Conflict | The request conflicts with the current state (e.g. duplicate order ID). |
422 | Business Logic Error | The request is structurally valid but violates an exchange rule. See the business error codes below. |
429 | Too Many Requests | Credit quota exhausted. Back off and retry. See Rate Limits. |
500 | Internal Server Error | Unexpected server-side error. Also returned when price or amount are not valid multiples of tick_size / lot_size. |
503 | Service Unavailable | Server is temporarily unable to handle requests. |
504 | Gateway Timeout | The upstream service did not respond in time. |
Business Logic Errors (HTTP 422)
A 422 response body contains a numeric code that identifies the specific rule violation. These codes are stable across API versions and safe to match programmatically.
| Code | Name | Description |
|---|
0 | UNKNOWN | An unclassified business logic error. |
1 | ACCOUNT_NOT_FOUND | The specified account address does not exist on Pacifica. |
2 | BOOK_NOT_FOUND | The order book for the requested market symbol was not found. Check the symbol casing. |
3 | INVALID_TICK_LEVEL | The price is not a valid multiple of the market’s tick_size. |
4 | INSUFFICIENT_BALANCE | The account does not have enough collateral to place this order or execute this withdrawal. |
5 | ORDER_NOT_FOUND | The referenced order ID does not exist or has already been filled/cancelled. |
6 | OVER_WITHDRAWAL | The withdrawal amount exceeds the available withdrawable balance. |
7 | INVALID_LEVERAGE | The requested leverage is outside the allowed range for this market. |
8 | CANNOT_UPDATE_MARGIN | The margin mode cannot be changed while there is an open position in this market. |
9 | POSITION_NOT_FOUND | No open position exists for the specified account and market. |
10 | POSITION_TPSL_LIMIT_EXCEEDED | The number of TP/SL orders on this position has reached the maximum allowed. |
A typical 422 response body looks like:
{
"error": "Insufficient balance",
"code": 4
}
WebSocket Error Codes
WebSocket action responses carry a numeric status code in the code field of the response envelope. A 200 indicates success; all other values signal a problem.
| Code | Name | Description |
|---|
200 | SUCCESS_CODE | The action was accepted and processed successfully. |
400 | INVALID_REQUEST_CODE | The request message is malformed or missing required fields. |
401 | INVALID_SIGNATURE_CODE | The signature attached to the action is invalid. |
402 | INVALID_SIGNER_CODE | The signer (agent wallet or account) is not authorised for this action. |
403 | UNAUTHORIZED_REQUEST_CODE | The account is not permitted to perform this action. |
420 | ENGINE_ERROR_CODE | The matching engine encountered an error processing the action. |
429 | RATE_LIMIT_EXCEEDED_CODE | Credit quota exhausted on this connection. |
500 | UNKNOWN_ERROR_CODE | An unexpected error occurred. |
A typical WebSocket error response looks like:
{
"id": "req-001",
"code": 401,
"msg": "Invalid signature"
}
Handling Errors in Code
Wrap every API call in error handling that inspects both the HTTP status code and, for 422 responses, the body’s code field. The pattern below covers the most common cases:
import requests
def place_order(payload: dict, headers: dict) -> dict:
response = requests.post(
"https://api.pacifica.fi/api/v1/orders/create",
json=payload,
headers=headers,
)
if response.status_code == 200:
return response.json()
# Attempt to parse JSON error body
try:
body = response.json()
except ValueError:
body = {"error": response.text}
if response.status_code == 400:
raise ValueError(f"Bad request — check signature or payload: {body}")
if response.status_code == 403:
raise PermissionError(f"Forbidden — region may be restricted: {body}")
if response.status_code == 422:
code = body.get("code", 0)
msg = body.get("error", "Business logic error")
# Match on specific codes for structured handling
if code == 4:
raise RuntimeError(f"Insufficient balance: {msg}")
if code == 5:
raise RuntimeError(f"Order not found — already filled or cancelled: {msg}")
if code == 3:
raise ValueError(f"Invalid tick level — price is not a multiple of tick_size: {msg}")
raise RuntimeError(f"Business logic error [{code}]: {msg}")
if response.status_code == 429:
# Caller should implement exponential back-off — see Rate Limits docs
raise RuntimeError("Rate limit exceeded (429). Back off and retry.")
if response.status_code >= 500:
raise RuntimeError(f"Server error [{response.status_code}]: {body}")
raise RuntimeError(f"Unexpected status {response.status_code}: {body}")
For WebSocket, inspect the code field in every action response envelope:
import json
def handle_ws_response(raw_message: str) -> None:
msg = json.loads(raw_message)
code = msg.get("code")
if code == 200:
print("Action succeeded:", msg)
return
if code == 401:
raise ValueError("Invalid signature — re-check signing logic.")
if code == 429:
print("Rate limited over WebSocket — slow down.")
return
raise RuntimeError(f"WebSocket error [{code}]: {msg.get('msg', 'unknown error')}")
Signing-Specific 400 Errors
Malformed or expired signatures return HTTP 400 with one of these message strings in the body:
| Message | Common Causes |
|---|
"Invalid signature" | Not valid Base58; decoded bytes are not a valid Ed25519 signature |
"Invalid message" | Message has expired (timestamp + expiry_window < server_time); payload cannot be serialised to JSON |
"Invalid public key" | account field is not a valid Base58-encoded Ed25519 public key |
"Verification failed" | Signature is valid in form but does not match the message; wrong key was used, or the payload was modified after signing |
The quickest way to eliminate signing errors is to use the Pacifica Python SDK, which handles key parsing, deterministic JSON serialisation, and Base58 encoding automatically. See Authentication for a full step-by-step breakdown of the manual signing process.