Skip to content

Limits & Errors

This page summarizes rules shared across APIs. Required fields, lifecycle behavior, and model-specific semantics still belong to each API page.

ItemLimit
Request body sizeMax 32 KiB (32,768 bytes).
channel_id128-bit Crockford Base32. Canonical output is 26 uppercase characters; input is case-insensitive, ignores ASCII whitespace and hyphens, and accepts Crockford aliases O0 and I/L1.
Gateway-generated entity IDs32 lowercase hex characters. Client-supplied Event/Thing IDs on non-create routes may use the general format below.
Channel passwordTrimmed before validation, then 8-128 bytes.
op_idClient input: 1-128 characters using letters, digits, _, :, -, supported by Message only. Generated values currently use 13 lowercase hex timestamp characters, a hyphen, and 32 lowercase hex random characters; treat the generated value as opaque.
thing_id / event_id1-64 characters; letters, digits, _, :, -.
imagesUp to 32 URLs, max 2048 bytes each.
tagsUp to 32 tags, max 64 bytes each, trimmed and deduplicated.
metadataScalar values only; key max 64 bytes, non-empty scalar text max 512 bytes; no nested objects, arrays, or null.
ttl and API timestampsUnix seconds or milliseconds accepted where documented; values normalize to milliseconds.
Active subscribersMax 32 concurrent subscribers per channel.
Built-in password request budgetPer Gateway process: 60 requests per IP per minute and 1,200 total per minute on public/password-sensitive and MCP/OAuth password surfaces. Private requests authenticated by the shared Bearer token bypass this limiter.
Unknown fieldsNative Message, Event, and Thing ignore extension fields for forward compatibility; known action-forbidden fields still return 400.

Message validates its tags, images, and severity as documented. Event and Thing patch content does not inherit those Message-specific limits.

Success:

{
"success": true,
"data": {
"op_id": "00191f23cc000-0123456789abcdef0123456789abcdef",
"message_id": "8a1fc4b3d9f04fd2857f92f66f7cc5d1"
}
}

Failure:

{
"success": false,
"error": "human readable message",
"error_code": "machine_readable_code",
"problem": {
"code": "machine_readable_code",
"category": "validation",
"status": 400,
"title": "Invalid request",
"detail": "human readable message",
"localized_message": "human readable message",
"locale": "en",
"retryable": false,
"request_id": "request-id"
}
}

Optional problem members are omitted when unavailable. The response also mirrors request_id in the x-request-id header when request scope provides one.

Success data contains op_id plus exactly one of message_id, event_id, or thing_id; it does not contain channel_id or an accepted boolean. Automation should prefer the HTTP status plus success, error_code, or problem.code over natural-language text.

success=true from a send API means the Gateway durably accepted the submission. It does not guarantee provider success, private-transport delivery, device display, or user visibility.

It does not guarantee:

  • Every device is online.
  • APNs or FCM has displayed a notification.
  • Android private transport delivered in real time.
  • The user is unaffected by notification permissions, Focus mode, or battery policy.

Query the returned operation ID with GET /send_status/{op_id}. The response contains op_id, status, model, entity_id, accepted_at, updated_at, and expires_at.

StatusMeaning
acceptedSubmission was durably accepted.
processingDispatch processing is underway.
provider_queuedQueued in the Gateway provider worker; not provider success.
sentDispatch completed without a recorded target failure.
partially_failedAt least one dispatch target failed.
failedSubmission processing failed.

An unknown or expired operation ID returns 404 send_status_not_found. This is coarse dispatch state, not an end-device display receipt.

StatusMeaningTypical reasonWhat to do
200Gateway processed the requestsuccess=trueStore returned IDs and op_id.
400Validation failedMissing/invalid field or a known field is forbidden for the actionCompare the JSON with the API field table.
401Gateway authentication failedPrivate Gateway uses PUSHGO_TOKEN; Bearer token missing or wrongCheck Authorization: Bearer <token>.
404Target missingChannel or sender-status record does not existCheck channel_id or op_id.
409Idempotency conflictMessage op_id reused with another normalized payload or scopeGenerate a new operation ID or resend the original payload.
413Request body too largeJSON exceeds 32 KiB (32,768 bytes)Use image URLs; reduce metadata or attrs.
429Request rate limitedA built-in per-process password request budget was exceededRetry later and reduce bursts.
503Submission not acceptedGateway admission or durable submission failedInspect Gateway logs, storage health, and capacity.
  • JSON must be valid.
  • Do not send event_id to /event/create or thing_id to /thing/create.
  • Do not supply op_id to Event or Thing routes, or generated IDs to create routes.
  • For Message, severity should be critical, high, normal, or low; unknown values normalize to normal.
  • Unknown extension fields are ignored, so verify field spelling when an optional value has no effect.
  • Check whether the private Gateway has PUSHGO_TOKEN.
  • Header must be Authorization: Bearer <token>.
  • Do not confuse channel password with Gateway token.
  • Ensure the reverse proxy does not strip Authorization headers.
  • If a private Gateway sets PUSHGO_TOKEN, /healthz and /readyz also require the Bearer token.

Request Succeeds but Device Does Not Notify

Section titled “Request Succeeds but Device Does Not Notify”
  • The client must be subscribed to the channel.
  • Device notification permission must be enabled.
  • Apple delivery can be affected by APNs, Focus modes, and system settings.
  • Android clients must be able to fetch the correct /gateway/profile.
  • Private transport ports, certificates, and external addresses must be reachable.
  • Gateway logs may show provider or private dispatch errors.
  • PUSHGO_PRIVATE_TRANSPORTS must be enabled.
  • WSS must be reachable through the HTTPS domain.
  • QUIC UDP port may be blocked by firewall or proxy.
  • Raw TCP must handle TLS or TLS offload correctly.
  • Advertised ports and actual bind ports may differ behind NAT or port mapping.
  • PUSHGO_MCP_ENABLED must be enabled.
  • For non-loopback deployment, PUSHGO_PUBLIC_BASE_URL must be an external HTTPS URL; loopback-only local development may omit it.
  • Reverse proxy must forward /.well-known/*, /oauth/*, and /mcp.
  • DCR must match client capability.
  • Bind page sessions can expire.