API Reference
Webhooks API
Verified partner webhook subscriptions, events, delivery signatures, delivery logs, retry behavior, and Node.js signature verification example.
SoundSync
Verified partner webhook endpoints
These endpoints require webhooks:read or webhooks:write partner API scopes.
/api/partner/v1/webhooks
List partner webhook subscriptions.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Returns
- webhooks[].
- Side effects
- None for GET endpoints unless noted.
- Notes
- Relationship-scoped partner key and operation-specific campaigns/webhooks read or write scope are required. External seller payments remain outside SoundSync managed-checkout processing coverage.
Request, response and error reference
No request body fields are read by this operation.
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"webhooks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"url": {
"type": "string"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"status": {
"type": "string"
},
"created_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
}
Documented failures: 400, 500.
/api/partner/v1/webhooks
Create a partner webhook subscription.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Request fields
- url: string (required)
- events: array
- description: string
- Returns
- 201 webhook plus one-time signing secret.
- Side effects
- Stores webhook subscription and generated signing secret. Secret is shown once.
- Notes
- Returns private signing material inside webhook.secret, not a top-level secret. Only url is required: omitted events defaults to order.fulfilled, order.refunded, license.revoked and webhook.test. An explicit event list must retain at least one supported event after normalization. Use public HTTPS without credentials or a nonstandard port. Fulfillment availability and webhook-write scope are required; do not publish a live secret.
Request, response and error reference
Request (application/json)
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"order.fulfilled",
"order.refunded",
"license.revoked",
"relationship.requested",
"relationship.updated",
"webhook.test"
]
}
},
"description": {
"type": "string"
}
},
"required": [
"url"
],
"additionalProperties": true
}
HTTP 201 response (application/json)
{
"type": "object",
"properties": {
"webhook": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"url": {
"type": "string"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"status": {
"type": "string"
},
"secret": {
"type": "string"
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Documented failures: 400, 500.
/api/partner/v1/webhooks/:webhookId
Update partner webhook subscription status/events/url/description or rotate secret when requested.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Request fields
- url: string
- events: array
- description: string
- rotate_secret: boolean
- status: string
- Returns
- webhook; includes secret only when rotation was requested.
- Side effects
- May rotate the webhook secret.
Request, response and error reference
Request (application/json)
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"description": {
"type": "string"
},
"rotate_secret": {
"type": "boolean"
},
"status": {
"type": "string"
}
},
"additionalProperties": true
}
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"webhook": {
"type": "object",
"properties": {},
"additionalProperties": true
},
"secret": {
"type": "string"
}
},
"additionalProperties": true
}
Documented failures: 400, 403, 404, 409.
/api/partner/v1/webhooks/:webhookId
Disable a partner webhook subscription.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Returns
- Disabled webhook response.
- Side effects
- Marks subscription disabled.
- Notes
- Disables the subscription rather than implying physical erasure of webhook delivery/audit history.
Request, response and error reference
No request body fields are read by this operation.
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"deleted": {
"type": "boolean"
},
"id": {
"type": "integer",
"minimum": 1
}
},
"additionalProperties": true
}
Documented failures: 400, 500.
/api/partner/v1/webhooks/test
Queue a partner webhook.test delivery.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Request fields
- message: string
- Returns
- success true and event { type webhook.test, id, relationship_id, partner_id, developer_id, created_at }.
- Side effects
- Queues webhook.test delivery.
Request, response and error reference
Request (application/json)
{
"type": "object",
"properties": {
"message": {
"type": "string"
}
},
"additionalProperties": true
}
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"event": {
"type": "object",
"properties": {
"type": {
"const": "webhook.test"
},
"id": {
"type": "string"
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Documented failures: 400, 403, 404, 409.
/api/partner/v1/webhook-events
List partner webhook delivery attempts/events.
- Auth
- Relationship-scoped partner API key
- Scope
- Public, customer-token, developer-user, or scoped partner API surface as noted.
- Request fields
- query limit: integer
- Returns
- events[] with type/event_id/status/attempt_count/next_attempt_at/last_status_code/last_error/response_preview.
- Side effects
- None for GET endpoints unless noted.
- Notes
- Relationship-scoped partner key and operation-specific campaigns/webhooks read or write scope are required. External seller payments remain outside SoundSync managed-checkout processing coverage.
Request, response and error reference
Query and header parameters
[
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"required": false,
"description": ""
}
]
No request body fields are read by this operation.
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"events": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"type": {
"type": "string"
},
"endpoint": {
"type": "string"
},
"method": {
"type": "string"
},
"request_id": {
"type": [
"string",
"null"
]
},
"idempotency_key": {
"type": [
"string",
"null"
]
},
"external_order_id": {
"type": [
"string",
"null"
]
},
"status_code": {
"type": "integer"
},
"success": {
"type": "boolean"
},
"error_code": {
"type": [
"string",
"null"
]
},
"error_message": {
"type": [
"string",
"null"
]
},
"request_summary": {
"type": "object",
"additionalProperties": true,
"description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
},
"response_summary": {
"type": "object",
"additionalProperties": true,
"description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
},
"created_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": true
}
},
"deliveries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"subscription_id": {
"type": [
"integer",
"null"
]
},
"type": {
"type": "string"
},
"event_id": {
"type": "string"
},
"status": {
"type": "string"
},
"attempt_count": {
"type": "integer"
},
"next_attempt_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_attempt_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_status_code": {
"type": "integer"
},
"last_error": {
"type": [
"string",
"null"
]
},
"response_preview": {
"type": "string"
},
"created_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
}
Documented failures: 400, 500.
SoundSync
Verified partner webhook event types
Only events accepted by normalizeWebhookEvents are listed.
| Event | When it is used |
|---|---|
| order.fulfilled | Queued when partner external order fulfillment succeeds. |
| order.refunded | Supported subscription event type for partner webhook subscriptions. |
| license.revoked | Supported event type for partner license revocation. |
| relationship.requested | Supported relationship lifecycle event. |
| relationship.updated | Supported relationship lifecycle event. |
| webhook.test | Queued by partner webhook test endpoints. |
SoundSync
Node.js signature verification
Partner webhook delivery signs the exact JSON body with HMAC-SHA256 and sends X-SoundSync-Signature: sha256=<hex>. The current partner implementation does not include a timestamp header, so timestamp tolerance must not be claimed as implemented.
const crypto = require('crypto');
function verifySoundSyncPartnerWebhook({ rawBody, signatureHeader, secret }) {
const supplied = String(signatureHeader || '').replace(/^sha256=/, '');
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const suppliedBuffer = Buffer.from(supplied, 'hex');
const expectedBuffer = Buffer.from(expected, 'hex');
return suppliedBuffer.length === expectedBuffer.length
&& crypto.timingSafeEqual(suppliedBuffer, expectedBuffer);
}
Delivery behavior
The delivery worker posts JSON with User-Agent SoundSync-Partner-Webhooks/1.0, X-SoundSync-Event, X-SoundSync-Event-Id, and X-SoundSync-Signature. 2xx responses are success via response.ok; failures are retried by queued/failed delivery attempts with next_attempt_at and attempt_count.
