Integrations

Partner API errors and limits

Every error code the partner API returns, what it means, how to fix it, and the limits behind the rate and retry rules.

On this page

Every error response has the same shape. Use code for program logic, message for diagnostics, and request_id when contacting Snapbar. The doc_url in each response links to the matching section on this page. param, required_scopes, and granted_scopes appear only when relevant.

HTTP status by code

  • 400 invalid_request, invalid_cursor, attestation_required_in_dashboard

  • 401 invalid_api_key

  • 402 insufficient_credits

  • 403 missing_scope, integrations_disabled, test_mode_forbidden

  • 404 resource_not_found, route_not_found

  • 409 activation_not_accepting, idempotency_conflict, endpoint_limit_reached, hook_endpoint_disabled, removal_requested, replay_verification_required, delivery_not_replayable

  • 413 payload_too_large

  • 422 media_unfetchable, terms_consent_required

  • 429 rate_limit_exceeded

  • 500 internal_error

  • 503 rate_limit_unavailable, ingest_outcome_unknown, service_unavailable

Error response shape

  • A validation failure on the limit query parameter looks like this.

    {
      "error": {
        "type": "invalid_request_error",
        "code": "invalid_request",
        "message": "Number must be greater than or equal to 1",
        "param": "limit",
        "doc_url": "https://dashboard.snapbar.com/help/partner-api-errors-and-limits#invalid-request",
        "request_id": "c0a8012e-4f2b-4b7d-9c1e-6d3a8f5b2e10"
      }
    }

activation_not_accepting

  • Meaning: HTTP 409. The activation is not active and unlocked, or it has no published release. The check runs before any media is fetched.

  • Fix: Activate and unlock the activation and publish a release, then retry with the same request and Idempotency-Key. A release whose styles are all inactive answers resource_not_found instead.

attestation_required_in_dashboard

  • Meaning: HTTP 400. The request tried to register a webhook endpoint with consent_policy: "all_leads", which cannot be confirmed through the API.

  • Fix: Use marketing_consented, or media_only when the destination only needs photos and no lead data.

delivery_not_replayable

  • Meaning: HTTP 409. The delivery is not in a replayable state, or its data was erased for privacy. Eligible states are failed_retryable, failed_permanent, skipped_disabled, and unknown. A replay whose endpoint has since been deleted or disabled is accepted and then closes again as skipped_disabled when the sender claims it.

  • Fix: Read the delivery again and compare its status with the status table in Partner API reference. Do not replay work that is pending, delivering, succeeded, paused, skipped_consent, or skipped_no_contact; a skipped_disabled row for a retracted approval revives on its own when the photo is approved again.

endpoint_limit_reached

  • Meaning: HTTP 409. The account already holds 50 active webhook endpoints. Disabled endpoints do not count.

  • Fix: Delete an unused endpoint with DELETE /webhook-endpoints/{id} to free a slot, then retry.

hook_endpoint_disabled

  • Meaning: HTTP 409. Only the hook subscription routes reserved for automation partners return this. POST /hooks matched an existing subscription for the same address, event, and activation that was disabled, either by an unsubscribe or by Snapbar after repeated failures. A disabled subscription cannot be re-enabled, and it blocks a new subscription at the same address.

  • Fix: Delete the disabled subscription with DELETE /hooks/{id}, using the id from its original subscribe response, then subscribe again with a new secret. Endpoints registered through POST /webhook-endpoints never return this code; a disabled one is deleted with DELETE /webhook-endpoints/{id} and re-registered in the same way.

idempotency_conflict

  • Meaning: HTTP 409. With a Retry-After header, an ingest request with this Idempotency-Key is still in flight. Without one, the key was used within the last 24 hours with a different body. Keys are scoped to the account and shared by every API key in it, and only a successful response is stored; a failed request releases its key.

  • Fix: When the response carries Retry-After, wait that long and retry the same key and identical body; keep retrying, because a request that never finished releases its key after ten minutes, and this is the normal follow-up to ingest_outcome_unknown. Without Retry-After, the body changed: resend the original body, or use a new key for a new logical submission, and make key values unique across every application that ingests for the account. A stored key expires after 24 hours, after which the same key creates a second submission and spends a second credit.

insufficient_credits

  • Meaning: HTTP 402. The activation has no available credit for the ingest request. The check runs before any media is fetched.

  • Fix: Add credits to the activation, then retry with the same Idempotency-Key.

integrations_disabled

  • Meaning: HTTP 403. The key is valid, but integrations are not enabled for its account. Every operation is rejected while the account is disabled, and queued deliveries pause rather than fail.

  • Fix: Contact Snapbar to enable integrations for the account. Requests succeed again as soon as it is enabled, and paused deliveries resume on their own.

internal_error

  • Meaning: HTTP 500. Snapbar could not complete the request because of an internal failure.

  • Fix: Retry with backoff if the operation is safe to repeat. Keep the request_id and contact Snapbar if it continues.

invalid_api_key

  • Meaning: HTTP 401. The bearer token is missing, malformed, revoked, or not recognized. Snapbar answers this when the header carries no well-formed key, or when it looked the key up and refused it. When the lookup itself could not run, the answer is [service_unavailable](#service-unavailable) instead: the key was not checked, so it was not rejected.

  • Fix: Send Authorization: Bearer <key> with a current key whose value starts with sbk_live_ or sbk_test_. Create a replacement if the full value was lost.

invalid_cursor

  • Meaning: HTTP 400. The pagination cursor is malformed or cannot be decoded.

  • Fix: Pass the exact next_cursor from the preceding page. Do not edit a cursor or reuse it for a different collection.

invalid_request

  • Meaning: HTTP 400. A path value, query value, JSON body, header, or field failed validation, including malformed JSON. param names the field. Receiver address failures use param: "url": plain HTTP, credentials in the address, a non-default port, a private or loopback IP address written as a literal, or an invalid endpoint address. A hostname such as localhost is not resolved here; it passes and fails later at delivery. An input_data.prompt longer than the published style’s model cap (4,000 for Seedream 4.5/5 Pro, otherwise up to 10,000) is rejected here with param: "input_data.prompt".

  • Fix: Check param, then compare the request with the OpenAPI document. Send valid JSON with Content-Type: application/json where a body is required. Receiver addresses must be public HTTPS on port 443 with no credentials and a hostname that resolves publicly.

media_unfetchable

  • Meaning: HTTP 422. Snapbar could not safely fetch or rehost a supplied media link, or the file was not a supported image within 20 MB.

  • Fix: Supply a public HTTPS image link that returns a valid image without redirects, then retry.

missing_scope

  • Meaning: HTTP 403. The key does not include every scope the operation needs. The response lists granted_scopes and, when the route can name them, required_scopes.

  • Fix: Create a new key with the required presets. Add read lead details when requesting include_lead=true, and manage notification endpoints for GET /hooks/sample and POST /test/deliveries.

payload_too_large

  • Meaning: HTTP 413. A JSON body exceeded 256 KiB, or an ingest body, its input_data, or its lead_data.custom_fields exceeded its own limit.

  • Fix: Keep an ingest body within 64 KiB, input_data within 48 KiB, and lead_data.custom_fields within 8 KiB; keep every other body within 256 KiB.

rate_limit_exceeded

  • Meaning: HTTP 429. A one-minute window was exceeded. param says which: ip for the 600 per source address window, key for the 300 per key window, the 60 per key ingest window (that response reports RateLimit-Limit: 60), or the 10 per key test delivery window.

  • Fix: Stop until Retry-After has elapsed, then use the rate limit headers to pace later requests.

rate_limit_unavailable

  • Meaning: HTTP 503. Only POST /activations/{id}/submissions returns this. The ingest rate limiter could not be reached, and Snapbar refuses to spend a credit without it, so no submission was created and no credit was spent.

  • Fix: Retry after Retry-After, or after a short backoff when the header is absent, with the same body and Idempotency-Key. Keep the request_id and contact Snapbar if it continues.

removal_requested

  • Meaning: HTTP 409. The submission carries an active participant removal request, so its media cannot be unhidden. The participant asked the event organizer to take their photo down, and Snapbar keeps it hidden from public displays and sharing until a host resolves the request.

  • Fix: Open the submission in the Snapbar dashboard and choose Restore public visibility. Unhide through the API again once the request is resolved. Hiding media is never blocked by this code.

replay_verification_required

  • Meaning: HTTP 409. The delivery outcome is unknown and the replay did not confirm that the receiver failed to process the first attempt.

  • Fix: Search the destination for the delivery idempotency key or event id. Replay with {"verified": true} only after confirming the original operation did not take effect.

resource_not_found

  • Meaning: HTTP 404. The activation, submission, delivery, webhook endpoint, media item, or style named by definition_key does not exist in the key account or is not visible to that key. A submission in any processing state is readable, so this is never a sign that processing is still running.

  • Fix: Confirm the identifier and the account. Treat the response as nonexistence rather than inferring that another account owns the resource.

route_not_found

  • Meaning: HTTP 404. No route matches the requested method and path.

  • Fix: Check the method, the /v1 prefix, and the path against the Partner API reference.

service_unavailable

  • Meaning: HTTP 503. Snapbar could not check the API key because something it depends on was temporarily unavailable. The key was not rejected, and the request stopped before it reached the operation, so nothing was read, created, or charged.

  • Fix: Retry after Retry-After with the same body, and the same Idempotency-Key on an ingest. Do not replace the key. Keep the request_id and contact Snapbar if it continues.

ingest_outcome_unknown

  • Meaning: HTTP 503. Snapbar could not confirm whether an ingest transaction committed. The photo may already exist and its credit may already be spent.

  • Fix: Wait for Retry-After, then resend the same body with the same Idempotency-Key. Keep request_id. Never create a fresh key to retry an uncertain ingest. Contact support before retrying after the 24-hour replay window.

test_mode_forbidden

  • Meaning: HTTP 403. A test key called a route other than metadata/sample reads: GET /activations or GET /hooks/sample.

  • Fix: Use a live key for that route. What a test key can do, and which preset each of its two routes still needs, is in Create API keys.

Rate limits

  • 300 requests per API key and 600 per source address per fixed one-minute window; POST /activations/{id}/submissions allows 60 per key per minute, and POST /test/deliveries allows 10 per key per minute. Several keys behind one address share the address window.

  • Every response from the API carries RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset (Unix seconds), and X-Request-Id. A 429 from the API adds Retry-After in seconds. You may supply your own X-Request-Id of up to 128 characters and it is echoed back.

  • A request blocked at the network edge (a flood of requests, or a request that looks like an attack) receives a plain 403 or 429 without the JSON error body and without the RateLimit or Retry-After headers. Treat any 403 or 429 that is not JSON as a signal to stop and back off for several minutes: a flood block lasts ten minutes, and retrying during it extends nothing but wastes your requests.

Request limits

  • Collection limit defaults to 20 and is capped at 100; a status filter names at most 10 values.

  • An endpoint subscribes to one to three event types and can be scoped to at most 100 experiences; an account holds at most 50 active endpoints.

  • Any JSON request body is limited to 256 KiB. Ingest bodies are limited to 64 KiB, input_data to 48 KiB, input_data.prompt to the selected style’s cap (4,000 for Seedream 4.5/5 Pro; otherwise up to 10,000), lead_data.custom_fields to 8 KiB, three images per request, and 20 MB per image.

Delivery retry ladder

How a failed delivery to a webhook endpoint or a managed destination is retried, and when Snapbar stops. This is the one place the schedule lives; Fix failed deliveries explains how each stage appears in Activity.

Schedule

nine attempts
  • The first attempt normally follows event processing promptly; approved photos include a 10-second retraction window and queue pacing can add delay. Retries follow after 5 seconds, 1 minute, 5 minutes, 30 minutes, then 1 hour before each of four more attempts, nine attempts in total.
  • A valid Retry-After from the receiver extends a shorter delay, capped at 3,600 seconds.

What is retried

temporary
  • HTTP 408, 425, 429, any 5xx, a network failure, a timeout (the receiver has exactly 10 seconds), and a 3xx other than 301 or 308.
  • A Slack rate limit or outage on a managed destination.

What is permanent

Action needed
  • Any other 4xx, a 301 or 308 redirect, a hostname that resolves to a private or loopback address, and a delivery whose ninth attempt failed. A hostname that does not resolve at all is treated as unreachable and retried.
  • A photo sent to an endpoint that is already Failing gets a single attempt.

Pacing and health

ceilings
  • At most three deliveries are in flight per webhook endpoint and per managed connection at a time; the rest wait 30 seconds and try again. Managed destinations also have a daily budget (20,000 for Slack).
  • Five consecutive failures put an endpoint into Failing; a further failure more than seven days after the streak began disables it, which closes its undelivered rows as skipped. One success resets the streak.

What to know

  • Test the rules before the event.Use sample envelopes or test keys for parsing and metadata checks. Use a live manage-webhooks key and an already registered endpoint for signed synthetic network tests. Missing-scope, registration, credit spending, and idempotency behavior require a live key in an isolated rehearsal activation with an agreed credit budget; a test key cannot exercise those routes.

Tips

  • Log request_id with every failed call so support can find it.
  • Treat 429 as a signal to slow down, not to retry immediately.

Related articles

Partner API referenceCreate API keys for the partner APIReceive signed webhooks at your own endpointFix failed deliveries