Share a Wish

Error Codes

Every error response of the Share a Wish Public API is JSON with a machine-readable error code and an HTTP status. Some responses add a human-readable message, a hint, a db_error string or flags such as trial_expired. Match on the code, not on the message.

HTTP/1.1 403 Forbidden
Content-Type: application/json

{ "error": "origin_not_allowed" }

Unexpected exceptions are caught per handler and answered with { "error": "Internal server error" } and status 500 (a few older consumer routes use similar plain-text messages such as Not found or Product not found). The tables below list every snake_case code found in the API source, grouped by the area that emits it.

Widget — /widget/init, /widget/save, /widget/saved-products, OAuth bridge

CodeStatusMeaning
invalid_input400Missing public_key / origin on init, or missing URL on prefetch.
unknown_key403The public key does not exist or is not active.
origin_not_allowed403The request origin is not on the key's domain allow-list (localhost is always allowed).
allowlist_required403A pk_live_ key created after 2026-09-01 has no allowed domain yet. Response includes a hint.
subscription_required403Linked Shopify shop has an expired trial and no active subscription. Body contains message and trial_expired: true.
usage_limit_reached402/widget/save: the partner is on the Free plan and has used its 200 wishlist actions for the calendar month — saving is paused until the next month or an upgrade. Body: message, plan: "free", actions_limit, upgrade_url. Show a friendly "wishlist paused" notice, do not retry. Paid plans never get this error (they pay per extra action, see Overage).
forbidden403Widget token missing or invalid on a token-protected widget route.
unauthorized401User token missing or invalid.
missing_wishlist400wishlistId absent in the save request.
missing_url400product.url absent in the save request.
invalid_wishlist403The wishlist does not belong to the authenticated user.
product_create_failed500The product could not be created or found; db_error carries the database message.
save_failed500The wishlist item could not be written.
missing_state400OAuth bridge: state parameter missing.
invalid_session_data400OAuth bridge: session payload malformed.
invalid_or_expired_state400OAuth bridge: state unknown or expired.
invalid_session400Session store: access or refresh token missing.
invalid_access_token401Session store: the supplied access token is not valid.
missing_sid400Session store/restore: session id missing.
internal_error500Unexpected failure in the OAuth / session routes.

SDK client-side codes (error event, WidgetError.code)

CodeMeaning
popup_blockedThe browser blocked the popup — call open() from a user gesture.
init_no_token/widget/init answered without a token.
key_requiredinit() was called without a key.
not_initialisedopen() / mount() called before init().
mount_target_not_foundThe selector passed to mount() matched no element.

Server codes from /widget/init are passed through unchanged (err.code), with err.trial_expired set for subscription_required.

Hosted lists — /hosted/*

CodeStatusMeaning
unauthorized401User token missing or invalid.
forbidden403The user is neither owner nor editor of the list, or not the owner where required.
not_found404List, item or product not found — also for private lists on the public routes.
missing_token400Share token path parameter missing.
missing_id400Product id missing (DELETE /hosted/products/{productId}).
missing_item_id400Item id missing.
missing_params400Required path/body parameters missing (items, move, rescrape, collaborators).
missing_name400name missing when creating a list.
missing_title400title missing when adding a manual item.
missing_wishlist / missing_url400Save request incomplete.
invalid_wishlist403The wishlist does not belong to the user.
product_create_failed500Product upsert failed; db_error included.
save_failed500Wishlist item could not be written.
update_failed500Purchased flag / item update failed.
override_delete_failed / item_delete_failed400Deleting the item's price override or the item itself failed.
item_not_deleted500Item still exists after delete.
missing_target / same_list400Move: target list missing or identical to the source.
move_requires_owner403Only the owner may move items between lists.
insert_failed / source_delete_failed500Move: insert into target or delete from source failed.
no_canonical_url400Rescrape: the product has no URL to fetch.
manual_product400Rescrape: manual items cannot be scraped.
missing_user / self_invite400Collaborators: user id missing or inviting yourself.
not_a_friend403Collaborators can only be added from the owner's friends.
upsert_failed500Collaborator write failed.
link_failed / unlink_failed / internal_select_failed500Following / unfollowing a public list failed.
missing_data400Account bootstrap / migration body incomplete.
missing_identifier400Legacy login: identifier missing.
no_legacy_user404Legacy login: no matching user.
auth_failed / invalid_auth_response / db_insert_failed / db_error / user_init_failed / flag_update_failed500Anonymous user creation or legacy login failed.
old_user_not_found404Migration: the anonymous user does not exist.
old_user_not_anonymous400Migration: the source account is not anonymous.
migration_failed / internal_error500Migration failed.

Infrastructure, keys and usage — /api-usage/{apiKeyId}, /me/usage

CodeStatusMeaning
invalid_api_key_id400apiKeyId is not a number.
unauthorized401No bearer key, or the key does not match the requested id.
api_key_not_found404No key with that id.
plan_limits_not_found500The plan limits for the key's plan could not be loaded.
internal_server_error500Unexpected failure in the usage / image proxy routes.
partner_not_found404/me/usage: the portal user has no partner.
not_found404Unknown route (catch-all).

Baskets, shops, partners, analytics

CodeStatusMeaning
not_found404/baskets/{id}: basket configuration unknown; /partners/*: partner not found.
shop_not_found404Creator shop unknown or not published.
invalid_partner_id400/partners/{id}: id is not numeric.
no_partner404 / 403The user is not mapped to a partner (404 on /partners, 403 on media management).
no_linked_shop400Storefront listing requires a linked Shopify shop.
forbidden403Not the partner owner / not an allowed analytics origin.
partner_required400Analytics: partner id missing.
forbidden_key_not_owned / forbidden_key_mismatch403Analytics: the API key belongs to another partner.
api_key_not_found404Analytics: key unknown.
invalid_payload400/analytics/track: body malformed.

Media, images, scraper

CodeStatusMeaning
invalid_product_id400Product id missing or not numeric.
product_not_found404Product unknown.
invalid_shop_id400Shop id malformed.
unsupported_mime / invalid_bytes400Upload: file type not allowed or size not numeric.
file_too_large413Upload exceeds the size limit.
plan_limit_reached402Video quota of the creator plan reached.
invalid_storage_path / invalid_poster_path400Upload finalisation: storage paths malformed.
object_not_found409Upload finalisation: the object is not in storage yet.
invalid_id / invalid_position / invalid_status / nothing_to_update400Media update body invalid.
media_rejected409A rejected video cannot be re-activated.
not_found404Media item unknown.
invalid_or_disallowed_url400/images/proxy: URL missing or host not allowed.
upstream_errorupstream status/images/proxy: the origin server answered with an error; its status code is passed through and echoed as status.
missing_url400Scraper: URL missing.
internal_error500Scraper: unexpected failure.
scraper_not_configured, not_a_product_page, external_error, network_error, fetch_failed, fallback_scrape_failedScrape result codes returned inside the scrape payload (success: false), not as HTTP errors.

Consumer app — /me/*, /amazon/*, /feedback, /roles

These routes serve the Share a Wish app; listed for completeness.

CodeStatusMeaning
unauthorized401User token missing or invalid.
forbidden403Friend request does not belong to the user.
not_found404Notification, shared wishlist, Amazon list or item unknown.
not_found_or_not_pending404Friend request unknown or already handled.
missing_params / missing_token / missing_name / missing_wishlist / missing_friend_id / missing_recipient400Required parameter missing.
invalid_item_id400Item id not numeric.
invalid_code404Invite code unknown.
cannot_invite_self / self_request / cannot_unfriend_self400Friend actions targeting yourself.
update_failed / delete_failed / insert_failed / db_error / server_error / internal_error500Database operation failed.
missing_list_url / invalid_list_url / missing_amazon_list_id / missing_id / no_target_wishlist400Amazon import: request incomplete or URL not an Amazon list.
wishlist_not_owned403Amazon import: target wishlist belongs to someone else.
create_failed / sync_failed / internal500Amazon import failed.
invalid_idea / idea_too_long / invalid_rating / invalid_category400Feedback payload invalid.
submission_failed500Feedback could not be stored.

Discontinued services

CodeStatusMeaning
ad_studio_disabled410The AI Ad Studio (/ad-studio/* function) has been discontinued and archived on 2026-08-30. Every request except GET /ad-studio/health and GET /ad-studio/credits answers 410 Gone with message: "The AI Ad Studio has been discontinued (archived 2026-08-30)."