{"openapi":"3.1.0","info":{"title":"WickSpend Reseller API","version":"1.6.0","description":"Server-to-server API for WickSpend resellers: verification numbers, long rentals, Temp Mail, Marketplace, Boostly SMM, tenant-scoped notifications, and signed webhook events. Never expose your API key or webhook signing secret in browser JavaScript."},"servers":[{"url":"https://wickspend.com/api/v1"}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ApiError":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"code":{"type":"string"}}},"WebhookEnvelope":{"type":"object","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","example":"whd_123"},"type":{"type":"string","example":"number.sms.received"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","additionalProperties":true}}},"Notification":{"type":"object","properties":{"id":{"type":"integer"},"notification_id":{"type":"integer"},"type":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"body":{"type":"string"},"action_url":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"read":{"type":"boolean"},"is_read":{"type":"boolean"},"read_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}},"security":[{"ApiKey":[]},{"BearerAuth":[]}],"paths":{"/numbers/catalog":{"get":{"summary":"List live number offers","parameters":[{"name":"country_code","in":"query","schema":{"type":"string"}},{"name":"service_code","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Live WickSpend-priced catalog"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}},"/balance":{"get":{"summary":"Get reseller WickSpend wallet balance","responses":{"200":{"description":"Wallet balance"},"401":{"description":"Invalid API key"}}}},"/numbers/buy":{"post":{"summary":"Buy a verification number","description":"request_key is required for idempotency. Reusing the same request_key returns the existing order instead of creating another purchase.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["country_code","service_code","provider_id","request_key"],"properties":{"country_code":{"type":"string","example":"US"},"service_code":{"type":"string","example":"telegram"},"provider_id":{"type":"string","example":"auto"},"request_key":{"type":"string","example":"order-12345"}}}}}},"responses":{"200":{"description":"Purchased or duplicate existing order"},"202":{"description":"Provider state uncertain; do not retry with a new request_key"},"402":{"description":"Insufficient WickSpend wallet balance"},"409":{"description":"Purchase unavailable or failed"}}}},"/numbers/orders":{"get":{"summary":"List recent API number orders","responses":{"200":{"description":"Order list"}}}},"/numbers/status":{"get":{"summary":"Get one API order and OTP status","parameters":[{"name":"reference","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Order status and OTP when available"},"404":{"description":"Order not found"}}}},"/numbers/cancel":{"post":{"summary":"Cancel an active number","description":"Refund happens only after SMSBower confirms cancellation. Orders with received OTPs cannot be cancelled.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reference"],"properties":{"reference":{"type":"string"}}}}}},"responses":{"200":{"description":"Cancellation confirmed and refund completed, or duplicate already-refunded cancellation"},"409":{"description":"Not cancelable or provider did not confirm cancellation"}}}},"/marketplace/products":{"get":{"summary":"List WickSpend Marketplace products","description":"API-key authenticated view of the existing WickSpend Marketplace catalog. Manual products may appear but are currently read-only through the reseller API.","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Marketplace product page"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"}}}},"/marketplace/product":{"get":{"summary":"Get one Marketplace product","parameters":[{"name":"product_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Marketplace product"},"404":{"description":"Product not found"}}}},"/marketplace/orders":{"get":{"summary":"List reseller-owned Marketplace orders","responses":{"200":{"description":"Marketplace orders; delivery payload is returned only for fulfilled orders"},"401":{"description":"Invalid API key"}}}},"/marketplace/buy":{"post":{"summary":"Buy a provider-backed Marketplace product","description":"Uses the existing WickSpend Marketplace wallet/order/refund engine. manual: products currently return MANUAL_PRODUCT_API_UNSUPPORTED. request_key is reseller-scoped and idempotent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_id","request_key"],"properties":{"product_id":{"type":"string"},"quantity":{"type":"integer","minimum":1,"maximum":100,"default":1},"request_key":{"type":"string","example":"customer-market-order-123"}}}}}},"responses":{"200":{"description":"Fulfilled purchase or duplicate existing order"},"202":{"description":"Provider state uncertain; keep the same request_key and poll orders"},"402":{"description":"Insufficient WickSpend wallet balance"},"404":{"description":"Product or wallet not found"},"409":{"description":"Insufficient stock, manual product unsupported, or purchase failed"}}}},"/boostly/services":{"get":{"summary":"List live Boostly SMM services","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Boostly service page"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"},"503":{"description":"Provider or FX unavailable"}}}},"/boostly/service":{"get":{"summary":"Get one Boostly service","parameters":[{"name":"service_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Boostly service detail"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Service not found"},"429":{"description":"Rate limited"},"503":{"description":"Provider or FX unavailable"}}}},"/boostly/orders":{"get":{"summary":"List reseller-owned Boostly orders","responses":{"200":{"description":"Recent Boostly orders"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}},"/boostly/order":{"get":{"summary":"Get one reseller-owned Boostly order","parameters":[{"name":"reference","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Boostly order detail"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Order not found"},"429":{"description":"Rate limited"}}}},"/boostly/buy":{"post":{"summary":"Place a Boostly SMM order","description":"Uses WickSpend's existing Boostly pricing, wallet, provider and refund/reconciliation engine. request_key is reseller-scoped and idempotent. A 202 response means the provider state is uncertain; do not create a new request_key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service_id","target_link","quantity","request_key"],"properties":{"service_id":{"type":"string","example":"123"},"target_link":{"type":"string","format":"uri","example":"https://example.com/post"},"quantity":{"type":"integer","minimum":1,"example":1000},"request_key":{"type":"string","example":"boost-order-123"}}}}}},"responses":{"200":{"description":"Order placed or duplicate existing order"},"202":{"description":"Provider status unknown; keep the same request_key and poll the order"},"402":{"description":"Insufficient WickSpend wallet balance"},"404":{"description":"Service or wallet not found"},"409":{"description":"Quantity out of range or confirmed purchase failure"},"503":{"description":"Service/provider unavailable"}}}},"/rentals/catalog":{"get":{"summary":"List live long-rental offers","description":"API-key authenticated view of the existing WickSpend GotSMS rental catalog and WickSpend pricing.","responses":{"200":{"description":"Live rental services and periods"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"},"503":{"description":"Rental catalog unavailable"}}}},"/rentals/orders":{"get":{"summary":"List reseller-owned rental orders","responses":{"200":{"description":"Recent API rental orders"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}},"/rentals/order":{"get":{"summary":"Get one rental and current SMS/OTP messages","parameters":[{"name":"reference","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Owned rental status and stored/provider SMS messages"},"400":{"description":"Invalid reference"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Rental not found"},"429":{"description":"Rate limited"}}}},"/rentals/buy":{"post":{"summary":"Buy a WickSpend long rental","description":"Uses the existing WickSpend rental catalog, wallet, GotSMS credential and rental tables. request_key is reseller-scoped and idempotent. country_code is optional and defaults to US for backward compatibility. A 202 response means provider state is uncertain; do not create a new request_key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service_code","duration_minutes","request_key"],"properties":{"service_code":{"type":"string","example":"whatsapp"},"duration_minutes":{"type":"integer","enum":[1440,4320,10080,20160,43200],"example":1440},"request_key":{"type":"string","minLength":8,"example":"rental-order-123"},"country_code":{"type":"string","example":"US","description":"Optional GotSMS country code. Defaults to US."}}}}}},"responses":{"200":{"description":"Rental purchased or duplicate existing request"},"202":{"description":"Provider state uncertain; poll the same order"},"400":{"description":"Invalid service, duration or request key"},"401":{"description":"Invalid API key"},"402":{"description":"Insufficient WickSpend wallet balance"},"404":{"description":"Service or wallet not found"},"409":{"description":"Request-key conflict or confirmed purchase failure"},"503":{"description":"Rental catalog/offer unavailable"}}}},"/rentals/cancel":{"post":{"summary":"Cancel an active WickSpend long rental","description":"Refund is credited only after GotSMS confirms the rent refund/cancellation. Ambiguous provider responses return 202 without refunding.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reference"],"properties":{"reference":{"type":"string"}}}}}},"responses":{"200":{"description":"Cancellation confirmed and refunded, or already cancelled/refunded"},"202":{"description":"Provider cancellation status uncertain"},"400":{"description":"Invalid request"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Rental not found"},"409":{"description":"Rental not cancellable or provider rejected cancellation"}}}},"/temp-mail/services":{"get":{"summary":"List live Temp Mail services","description":"API-key authenticated view of the existing WickSpend Temp Mail/SMSBower catalog. Provider credentials are never exposed.","parameters":[{"name":"search","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Live Gmail service catalog"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"},"503":{"description":"Temp Mail catalog unavailable"}}}},"/temp-mail/price":{"get":{"summary":"Get live Temp Mail price and stock","parameters":[{"name":"service_code","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current WickSpend selling price and stock"},"400":{"description":"Invalid service code"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"},"503":{"description":"Price/provider unavailable"}}}},"/temp-mail/buy":{"post":{"summary":"Buy a temporary Gmail mailbox","description":"Uses the existing WickSpend Temp Mail wallet, SMSBower credential, trusted pricing and refund engine. request_key is reseller-scoped and idempotent. A 202 response means provider state is uncertain; do not retry with a new request_key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service_code","request_key"],"properties":{"service_code":{"type":"string","example":"wa"},"request_key":{"type":"string","minLength":8,"maxLength":120,"example":"mail-order-123"}}}}}},"responses":{"200":{"description":"Mailbox created or duplicate existing request"},"202":{"description":"Provider state uncertain; keep the same request_key"},"400":{"description":"Invalid service or request key"},"401":{"description":"Invalid API key"},"402":{"description":"Insufficient WickSpend wallet balance"},"403":{"description":"API access inactive"},"404":{"description":"Wallet not found"},"409":{"description":"Out of stock, request-key conflict, or confirmed provider failure"},"429":{"description":"Rate limited"},"503":{"description":"Price/provider unavailable"}}}},"/temp-mail/order":{"get":{"summary":"Get one Temp Mail order and OTP status","description":"Only orders owned by the authenticated reseller are visible.","parameters":[{"name":"reference","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Mailbox, OTP/status and cancellation eligibility"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Order not found"},"429":{"description":"Rate limited"}}}},"/temp-mail/cancel":{"post":{"summary":"Cancel an eligible Temp Mail order","description":"Refund is credited only after SMSBower confirms cancellation. Orders with an OTP, expired orders, and already-used mailboxes are not cancellable. Ambiguous provider cancellation returns 202 without refunding.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reference"],"properties":{"reference":{"type":"string"}}}}}},"responses":{"200":{"description":"Cancellation confirmed and refunded, or duplicate already-refunded cancellation"},"202":{"description":"Provider cancellation status uncertain; no refund yet"},"400":{"description":"Invalid request"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"404":{"description":"Order not found"},"409":{"description":"Order not cancellable or provider rejected cancellation"},"429":{"description":"Rate limited"}}}},"/temp-mail/orders":{"get":{"summary":"List reseller-owned Temp Mail orders","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Paginated Temp Mail order history"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}},"/notifications":{"get":{"summary":"List reseller notifications","description":"Returns only notifications belonging to the authenticated reseller owner. Supports unread-only filtering and pagination.","parameters":[{"name":"unread_only","in":"query","schema":{"type":"boolean","default":false}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Tenant-scoped reseller notifications"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}},"/notifications/read":{"post":{"summary":"Mark reseller notifications read","description":"Marks one notification by notification_id or all notifications with {\"all\":true}. The update is scoped to the authenticated reseller owner, so another reseller's notification cannot be changed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"notification_id":{"type":"integer","minimum":1},"all":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Read state updated"},"400":{"description":"Invalid request body"},"401":{"description":"Invalid API key"},"403":{"description":"API access inactive"},"429":{"description":"Rate limited"}}}}},"webhooks":{"wickspendEvent":{"post":{"summary":"Signed WickSpend event callback","description":"Configure a public HTTPS callback from the WickSpend reseller dashboard. WickSpend sends X-WickSpend-Event, X-WickSpend-Delivery, X-WickSpend-Timestamp and X-WickSpend-Signature. Derive the HMAC key as SHA256(signing_secret), then verify HMAC-SHA256 over timestamp + '.' + delivery_id + '.' + event_type + '.' + data.reference. Reject stale timestamps and deduplicate by delivery_id. Delivery retries occur up to five times.","parameters":[{"name":"X-WickSpend-Event","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-WickSpend-Delivery","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-WickSpend-Timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-WickSpend-Signature","in":"header","required":true,"schema":{"type":"string","example":"v1=abcdef..."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"}}}},"responses":{"200":{"description":"Any 2xx response acknowledges delivery"}}}}},"x-wickspend-webhook-events":["number.sms.received","number.refunded","marketplace.fulfilled","marketplace.refunded","boostly.completed","boostly.partial","boostly.refunded"]}