Skip to content
SoundSyncAudio software platform

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.

GET /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.

POST /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.

PATCH /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.

DELETE /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.

POST /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.

GET /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.

EventWhen it is used
order.fulfilledQueued when partner external order fulfillment succeeds.
order.refundedSupported subscription event type for partner webhook subscriptions.
license.revokedSupported event type for partner license revocation.
relationship.requestedSupported relationship lifecycle event.
relationship.updatedSupported relationship lifecycle event.
webhook.testQueued 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.

Node.js
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.