Skip to main content

Status Codes and Limits

Map each status code and error code from the API to its cause, and plan retries around the rate limits.

Status Codes

StatusError codeReturned byMeaning
200—All four routesThe action succeeded.
400invalid_requestPing, Wake-on-LANThe body failed validation, and issues lists each problem.
400invalid_jsonAny pathThe body isn't valid JSON.
401authentication_requiredAll four routesThe token is missing, malformed, unknown, or expired.
403scope_requiredAll four routesThe token lacks the route's scope.
404not_foundUnknown pathsNo route matches the method and path.
413payload_too_largeAny pathThe JSON body is larger than 64 KB.
415unsupported_encodingAny pathThe body uses a character set other than UTF-8, or a compression pfSense Actions can't read.
429rate_limitedAll four routes, and any path under /api/v1The client reached a rate limit.
500internal_errorAll four routesThe controller hit an unexpected error.
502pfsense_unavailableAll four routespfSense Actions couldn't sign in to pfSense over SSH.
502command_failedAll four routesThe pfSense command failed, or the system information route got unexpected output.
503connection_not_configuredAll four routesNo pfSense connection is saved yet, or its credential was removed.
503target_unreachablePingEvery ping attempt finished without meeting the selected reachability condition.

The console's own routes, including the notification routes, answer with codes of their own, such as session_required for a request with a token, as listed in Notifications.

Order of Checks

  1. The JSON body is parsed, so malformed JSON gets 400, an oversized body gets 413, and a body pfSense Actions can't decode gets 415.
  2. The rate limits apply, so a client over a limit gets 429 before anything else is checked.
  3. The token is checked for 401, then its scope for 403.
  4. The body is validated for 400.
  5. A route without a saved pfSense connection, or without its password or private key, answers 503.
  6. pfSense Actions signs in over SSH and runs the command, which ends in 200, 502, or 503.

Rate Limits

  • The four action routes share one limit of 3 requests per 10 seconds for each client IP address, whichever path a request uses.
  • Every path under /api/v1, including the console's, also counts toward a limit of 120 requests per minute for each address.
  • Requests rejected with 401 or 403 still count, and so do unknown paths under /api/v1, which end in 404.
  • Responses carry RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers. A 429 also carries Retry-After in seconds.
  • Behind a reverse proxy, the client address comes from X-Forwarded-For, as described in HTTPS Reverse Proxy.

The console's sign-in has its own limit on failed attempts, listed in the Security Model.

Retry Guidance

  • 429 — Wait for the number of seconds in Retry-After before sending again.
  • 500 or 502 — Retrying the connectivity, system information, or ping route is safe, because they don't change anything. Retrying Wake-on-LAN sends another wake packet.
  • 503 with target_unreachable — The device didn't meet the selected reachability condition, so retry later, raise count, or turn off strict mode when partial replies are enough.
  • 503 with connection_not_configured — Save the pfSense connection in the console first, or enter its password or private key again when error.message asks for it.
  • 400, 401, 403, 404, 413, or 415 — The same request keeps failing until something about it changes.

What Responses Never Contain

  • SSH output, the command that ran, or SSH error details.
  • Credentials, token values, or any token hash.
  • The firewall's hostname or configuration.