Guide
Errors and Status Handling
Stable documented SoundSync plugin licensing and Test Connection errors, retry guidance, lock behavior, and offline-grace implications.
SoundSync
Documented codes
These codes are verified in the contract catalog. Do not treat hard denials as offline-grace events.
| Code | HTTP | Meaning | Recommended action | Grace? |
|---|---|---|---|---|
| MISSING_CREDENTIALS | 400 | Test Connection body is missing productId, appId, pluginKey, or pluginSecret. | Fix request. Do not retry blindly. | No |
| INVALID_APP_ID | 401 | The App ID does not identify an active product credential row. | Use the App ID from the product credential panel or generated package. | No |
| INVALID_PLUGIN_KEY | 401 | Plugin key hash mismatch for the App ID. | Use the current plugin key; regenerate package after rotation. | No |
| INVALID_PLUGIN_SECRET | 401 | Plugin secret hash mismatch for the App ID. | Use the current secret. Do not ask customer for it. | No |
| REVOKED_CREDENTIAL | 403 | Credential was revoked. | Regenerate/rotate credentials and package config. | No |
| PRODUCT_MISMATCH | 403 | Credential belongs to a different product than productId. | Do not mix product config files. | No |
| SERIAL_NOT_FOUND | 404 | Serial/license key was not found. | Ask customer to check key or contact support. | No |
| SERIAL_PRODUCT_MISMATCH | 403 | Serial belongs to another product. | Check productId/app credentials and serial source. | No |
| CUSTOMER_DETAILS_REQUIRED | 200 | Serial requires customer identity before activation. | Open claim flow and collect email/customer details. | No |
| PENDING_EMAIL_VERIFICATION | 200 | Claim exists but customer has not completed email verification. | Keep activation UI open and poll/resume claim-status. | No |
| CLAIM_ACTIVATION_TOKEN_INVALID | 403 | Verified-claim activation token is invalid or expired. | Read claim-status again for fresh proof, then activate the same serial and machine. Restart /claim only when ownership verification itself requires it. | No |
| SERIAL_ACTIVATION_LIMIT_REACHED | 409 | Device limit is reached. | Show device-management/support path. | No |
| subscription_payment_required | 402 | Subscription is past due after payment grace. | Lock access and route to billing/support. | No |
| subscription_incomplete | 402 | Subscription checkout is incomplete. | Keep locked until checkout completes. | No |
| subscription_inactive | 403 | Subscription is canceled, unpaid, or expired. | Lock access and route to support/billing. | No |
| device_not_activated | 401 | Validation found no activation for this machine. | Clear invalid local state and require activation. | No |
| device_deactivated | 401 | This activation was deactivated. | Clear local state and require reactivation. | No |
Implementation-defined or under review
Any code not listed here should be displayed as an implementation-defined failure with sanitized diagnostics. Do not invent customer-facing copy for undocumented codes without adding it to the contract catalog first.
When a session cannot be checked
A signed account token must still match an active stored session. Revoked sessions return 401 SESSION_REVOKED. If the session store cannot be checked, protected account requests stop with 503 SESSION_VERIFICATION_UNAVAILABLE rather than continuing with unverified access.
Retry after a temporary availability problem. Do not treat 503 as permission to bypass authentication or automatically create a second payment, refund or other financial action. Reconcile the specific operation before repeating a write. Product credentials and customer library tokens have separate authentication contracts.
Password changes, recovery codes and sign-out
A successful password change saves the new password and revokes the other stored account sessions together. If revocation fails, the password change is rolled back and the request fails. With a recognized current token, that session is retained; without one, all stored sessions for the account are revoked.
Recovery codes are single-use, including concurrent attempts: only the request that consumes the code can complete that recovery-code sign-in. Disabling two-factor authentication checks the current password and factor against locked current account state. A failed logout returns 503 SESSION_REVOCATION_UNAVAILABLE, not a completed sign-out. Retry and do not treat client-side token removal as confirmation that the server session was revoked.
SoundSync
Finish sign-in before activating a device
| Result | Next action |
|---|---|
| 200 twoFactorRequired:true | Keep the plugin locked. Continue /api/auth/login with the returned private twoFactorToken, an authenticator or unused recovery code, the same customer email and role:customer. Omit the password on this continuation. |
| 401 Invalid two-factor code | Retry a current authenticator or unused recovery code within the existing challenge. Do not restart activation or create another account. |
| Expired challenge / two_factor_expired | Choose Start again and enter the password. Native challenges last up to ten minutes and do not survive restarting the plugin. |
| 403 EMAIL_VERIFICATION_REQUIRED | Verify the customer account email through its supported account flow, then sign in again. Account verification and serial ownership verification are separate. |
| Verified login returns token | Pass that account token as customer_token to /api/license/v1/customer-login/activate for the matching product and machine. A challenge token is not this account token. |
| 401 TWO_FACTOR_REQUIRED from direct password activation | Use the two-step account login instead. The direct licensing email/password compatibility branch cannot finish two-factor authentication. |
| Entitlement or device-limit denial | Use the ownership, billing or device-management recovery path. Account sign-in alone does not unlock the product or create offline grace. |
SoundSync
Serial claim outcomes and recovery
| Result | What to do |
|---|---|
| pending_email_verification | Keep the product locked. Save claim_id with the serial, customer email and machine identity. Complete the private verification link, then Restore or poll claim status. |
| verified + claim_activation_token | POST /api/license/v1/activate for the same serial and machine with claim_activation_token. Verification alone is not activation or a device reservation. |
| 400 VERIFICATION_RESTART_REQUIRED | The link was not sent or has expired. Submit the email and serial to /claim again; do not poll the expired claim indefinitely. |
| 503 VERIFICATION_EMAIL_FAILED / emailSent:false | Delivery was not confirmed. Wait for service recovery and deliberately retry the claim, or contact product support. HTTP failure does not grant access. |
| SERIAL_OWNER_EMAIL_MISMATCH / SERIAL_OWNER_LOGIN_REQUIRED | Sign in to the owning customer account, verify the owner email where supported, or contact support. Do not replace the owner email or create another identity to bypass the denial. |
| identity_required / CUSTOMER_DETAILS_REQUIRED | Provide the requested identity or use the owner-login path indicated by nextAction. HTTP 200 with ok:false is not a verified claim. |
| 429, timeout or temporary server error while polling/finalizing | Maintained native clients keep a pending claim for Restore to retry. Honor retry guidance; do not clear the cache or replace the machine identity merely to retry. No offline grant is created. |
| Revoked, refunded, expired or product-mismatched serial | Stop activation and follow the purchase/support path. These are access decisions, not an eligible connectivity failure. |
SoundSync
DNS check outcomes
| Response | Meaning and recovery |
|---|---|
| Nonempty stepKey on POST /check-step | Checks that record. step_key is an alias; copy the key from current returned records. |
| Omitted or empty key on POST /check-step | Checks all required or non-skipped records, not only currentStep. Supply a key for one-record checking. |
| 429 DNS_CHECK_COOLDOWN | Checks have an eight-second cooldown. Wait before retrying; do not loop or restart provider setup. |
| 409 DNS_SETUP_CHANGED | The saved setup changed during the check. Reload GET /api/developer/brand/domain, review current records, then deliberately retry. |
| 404 DNS_STEP_NOT_FOUND | The supplied key is absent from current setup. Reload rather than guessing another key. |
| 200 with pending/error records | Observed results were saved, not necessarily verified. DNS, provider activation, tracking SSL and identity are separate checks. |
SoundSync
Campaign action errors: recover without duplicate sends
| Operation / code | Next step |
|---|---|
| send-now: CAMPAIGN_SEND_STATE_INVALID, CAMPAIGN_STATE_CHANGED | Reload the campaign. Only send from a supported current state; do not repeat a completed send. |
| send-now: CAMPAIGN_SCHEDULED_NOT_DUE | Wait for the scheduled time or deliberately change the schedule through supported controls. |
| send-now: MARKETING_AUDIENCE_EMPTY | Review the eligible audience and exclusions. Do not override suppression or unsubscribe choices. |
| test, send-now, schedule, retry-failed: MARKETING_PROVIDER_DISABLED / MARKETING_PROVIDER_LOCKED / DEVELOPER_MARKETING_DISABLED | Resolve the named sending configuration or account readiness condition. These 409 responses do not authorize bypassing a gate. |
| MARKETING_FROM_EMAIL_REQUIRED / MARKETING_REPLY_TO_REQUIRED / MARKETING_BUSINESS_ADDRESS_REQUIRED / MARKETING_BRANDING_REQUIRED | Complete the verified sender, reply-to and required business identity/footer before trying again. |
| MARKETING_SUBJECT_REQUIRED / MARKETING_CONTENT_REQUIRED | Complete the message, preview it and then deliberately retry the intended action. |
| schedule: CAMPAIGN_NOT_SCHEDULABLE; INVALID_SCHEDULED_AT / INVALID_DELIVERY_TIMEZONE | Reload state for a 409 conflict. For a 400 input error, use a future date and a valid IANA timezone. |
| resume-send: CAMPAIGN_NOT_SENDING | Reload progress. Resume is for an existing sending campaign, not a resend command. |
| retry-failed: CAMPAIGN_RETRY_STATE_INVALID | Reload. Retry supports campaigns that started sending, not a new draft or analytics repair. |
| retry-failed: CAMPAIGN_RETRY_SCOPE_INVALID / CAMPAIGN_RETRY_CONFIRMATION_REQUIRED | Use safe or uncertain scope; uncertain requires confirmUncertain:true and accepts duplicate-delivery risk. Both input errors are 400. |
| cancel: CAMPAIGN_NOT_CANCELABLE / delete: CAMPAIGN_NOT_DELETABLE | Reload current state; an active send cannot be erased by deleting its campaign. |
| test: TEST_RECIPIENT_REQUIRED | Save the developer support recipient before testing. This 400 response does not allow arbitrary bulk recipients. |
