Skip to content
SoundSyncAudio software platform

API reference

Team Accounts API

Public developer Team Accounts API for listing members, creating/revoking invitations, accepting invitations, updating members, removing members, listing roles, and reading audit events.

SoundSync

Workspace membership operations

Never send a developer ID to choose another workspace.

GET /api/developer/team

Workspace, current access, members, pending invitations, roles

Auth
Account Bearer JWT
Scope
team.view; workspace and product assignments are resolved server-side.
Returns
Workspace, current access, members, pending invitations, roles
Side effects
Reads authorized team information.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "workspace": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "ownerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "displayName": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "currentAccess": {
      "type": "object",
      "properties": {
        "workspaceId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceOwnerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceDisplayName": {
          "type": "string"
        },
        "membershipId": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "effectiveDeveloperId": {
          "type": "integer",
          "minimum": 1
        },
        "isWorkspaceOwner": {
          "type": "boolean"
        },
        "role": {
          "type": "string"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "productScopeMode": {
          "type": "string"
        },
        "allowedProductIds": {
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "members": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "userId": {
            "type": "integer",
            "minimum": 1
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "productScopeMode": {
            "type": "string",
            "enum": [
              "all_products",
              "selected_products"
            ]
          },
          "selectedProductIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": true
      }
    },
    "invitations": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "productScopeMode": {
            "type": "string"
          },
          "selectedProductIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": true
      }
    },
    "roles": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true,
        "description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
      }
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

GET /api/developer/team/members

Team members only

Auth
Account Bearer JWT
Scope
team.view; workspace and product assignments are resolved server-side.
Returns
Team members only
Side effects
Reads authorized team information.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "members": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "userId": {
            "type": "integer",
            "minimum": 1
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "productScopeMode": {
            "type": "string",
            "enum": [
              "all_products",
              "selected_products"
            ]
          },
          "selectedProductIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": true
      }
    },
    "workspace": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "ownerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "displayName": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "currentAccess": {
      "type": "object",
      "properties": {
        "workspaceId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceOwnerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceDisplayName": {
          "type": "string"
        },
        "membershipId": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "effectiveDeveloperId": {
          "type": "integer",
          "minimum": 1
        },
        "isWorkspaceOwner": {
          "type": "boolean"
        },
        "role": {
          "type": "string"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "productScopeMode": {
          "type": "string"
        },
        "allowedProductIds": {
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

GET /api/developer/team/invitations

Pending invitations only

Auth
Account Bearer JWT
Scope
team.view; workspace and product assignments are resolved server-side.
Returns
Pending invitations only
Side effects
Reads authorized team information.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "invitations": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "productScopeMode": {
            "type": "string"
          },
          "selectedProductIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": true
      }
    },
    "workspace": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "ownerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "displayName": {
          "type": "string"
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

POST /api/developer/team/invitations

Creates one-time expiring email invitation; stores token hash only

Auth
Account Bearer JWT
Scope
team.invite; workspace and product assignments are resolved server-side.
Request fields
  • email: string (required)
  • role: administrator | product_manager | customer_support | marketing | analyst | billing | engineer (required)
  • productScopeMode: all_products | selected_products
  • selectedProductIds: array
Returns
201 { invitation, email }. The raw token is sent by transactional email, not returned in this JSON. Inspect the email outcome separately.
Side effects
Changes team membership or invitation state and records audit activity.
Notes
selected_products requires at least one owned product ID. Creation defaults to all_products. The raw token is emailed, not returned. The invitation expires after seven days; inspect the separate email outcome.
Request, response and error reference

Request (application/json)

{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    },
    "role": {
      "type": "string",
      "enum": [
        "administrator",
        "product_manager",
        "customer_support",
        "marketing",
        "analyst",
        "billing",
        "engineer"
      ]
    },
    "productScopeMode": {
      "type": "string",
      "enum": [
        "all_products",
        "selected_products"
      ]
    },
    "selectedProductIds": {
      "type": "array",
      "items": {
        "type": "integer",
        "minimum": 1
      }
    }
  },
  "required": [
    "email",
    "role"
  ],
  "additionalProperties": true
}

HTTP 201 response (application/json)

{
  "type": "object",
  "properties": {
    "invitation": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "role": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "expiresAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "productScopeMode": {
          "type": "string"
        },
        "selectedProductIds": {
          "type": "array",
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "email": {
      "type": "object",
      "additionalProperties": true,
      "description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

DELETE /api/developer/team/invitations/:invitationId

Revokes pending invitation

Auth
Account Bearer JWT
Scope
team.invite; workspace and product assignments are resolved server-side.
Returns
200 { invitation, revoked: true }. A missing or no-longer-pending invitation returns 404.
Side effects
Changes team membership or invitation state and records audit activity.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "invitation": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "role": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "expiresAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "productScopeMode": {
          "type": "string"
        },
        "selectedProductIds": {
          "type": "array",
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "revoked": {
      "type": "boolean"
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

POST /api/developer/team/invitations/accept

Accepts one-time token and creates membership

Auth
Account Bearer JWT
Scope
authenticated invited email; workspace and product assignments are resolved server-side.
Request fields
  • token: string (required)
Returns
200 { member, workspaceAccess }. Acceptance creates membership; repeated acceptance is rejected.
Side effects
Changes team membership or invitation state and records audit activity.
Notes
Sign in with the invited email. Used, expired, revoked and superseded invitations cannot grant access.
Request, response and error reference

Request (application/json)

{
  "type": "object",
  "properties": {
    "token": {
      "type": "string"
    }
  },
  "required": [
    "token"
  ],
  "additionalProperties": true
}

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "member": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "role": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "productScopeMode": {
          "type": "string",
          "enum": [
            "all_products",
            "selected_products"
          ]
        },
        "selectedProductIds": {
          "type": "array",
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "workspaceAccess": {
      "type": "object",
      "properties": {
        "workspaceId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceOwnerUserId": {
          "type": "integer",
          "minimum": 1
        },
        "workspaceDisplayName": {
          "type": "string"
        },
        "membershipId": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "effectiveDeveloperId": {
          "type": "integer",
          "minimum": 1
        },
        "isWorkspaceOwner": {
          "type": "boolean"
        },
        "role": {
          "type": "string"
        },
        "permissions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "productScopeMode": {
          "type": "string"
        },
        "allowedProductIds": {
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

PATCH /api/developer/team/members/:memberId

Changes role and product scope with owner/last-owner protections

Auth
Account Bearer JWT
Scope
team.manage_roles; workspace and product assignments are resolved server-side.
Request fields
  • role: owner | administrator | product_manager | customer_support | marketing | analyst | billing | engineer
  • productScopeMode: all_products | selected_products
  • selectedProductIds: array
Returns
200 { member, updated: true }. Existing sessions are revoked; the member may need to sign in again.
Side effects
Changes team membership or invitation state and records audit activity.
Notes
Send the complete selectedProductIds array for an existing selected_products member, including a role-only update. Owner assignment is owner-only; self-modification and removing the last active owner are prohibited. Existing sessions are revoked.
Request, response and error reference

Request (application/json)

{
  "type": "object",
  "properties": {
    "role": {
      "type": "string",
      "enum": [
        "owner",
        "administrator",
        "product_manager",
        "customer_support",
        "marketing",
        "analyst",
        "billing",
        "engineer"
      ]
    },
    "productScopeMode": {
      "type": "string",
      "enum": [
        "all_products",
        "selected_products"
      ]
    },
    "selectedProductIds": {
      "type": "array",
      "items": {
        "type": "integer",
        "minimum": 1
      }
    }
  },
  "additionalProperties": true
}

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "member": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "role": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "productScopeMode": {
          "type": "string",
          "enum": [
            "all_products",
            "selected_products"
          ]
        },
        "selectedProductIds": {
          "type": "array",
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "updated": {
      "type": "boolean"
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

DELETE /api/developer/team/members/:memberId

Revokes membership without deleting the user account

Auth
Account Bearer JWT
Scope
team.remove; workspace and product assignments are resolved server-side.
Returns
200 { member, removed: true }. Removes workspace access, not the user account; sessions are revoked.
Side effects
Changes team membership or invitation state and records audit activity.
Notes
Removes membership, not the user account; saved sessions are revoked.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "member": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1
        },
        "userId": {
          "type": "integer",
          "minimum": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "role": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "productScopeMode": {
          "type": "string",
          "enum": [
            "all_products",
            "selected_products"
          ]
        },
        "selectedProductIds": {
          "type": "array",
          "items": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "additionalProperties": true
    },
    "removed": {
      "type": "boolean"
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

GET /api/developer/team/roles

Returns canonical role and permission registry

Auth
Account Bearer JWT
Scope
authenticated developer; workspace and product assignments are resolved server-side.
Returns
200 { roles, permissions, productScopeModes, sensitivePermissions }.
Side effects
Reads authorized team information.
Request, response and error reference

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "roles": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true,
        "description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
      }
    },
    "permissions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "productScopeModes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "sensitivePermissions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

GET /api/developer/team/audit

Returns team audit events without sensitive tokens

Auth
Account Bearer JWT
Scope
team.audit.view; workspace and product assignments are resolved server-side.
Request fields
  • query limit: integer
Returns
200 { audit: [...] }. Treat email addresses and audit identities as private data.
Side effects
Reads authorized team information.
Request, response and error reference

Query and header parameters

[
  {
    "name": "limit",
    "in": "query",
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 50
    },
    "required": false,
    "description": ""
  }
]

No request body fields are read by this operation.

HTTP 200 response (application/json)

{
  "type": "object",
  "properties": {
    "audit": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "action": {
            "type": "string"
          },
          "actor_user_id": {
            "type": "integer",
            "minimum": 1
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Operation-specific extension data; do not put credentials or unnecessary personal information here."
          }
        },
        "additionalProperties": true
      }
    }
  },
  "additionalProperties": true
}

Documented failures: 400, 500, 503.

SoundSync

Create a selected-product invitation

Illustrative request; replace the address and product ID with values you are authorized to use. This sends an invitation when executed.

Invite a product manager
curl --fail-with-body -X POST "$SOUNDSYNC_API_BASE/api/developer/team/invitations" \
  -H "Authorization: Bearer $DEVELOPER_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"email":"teammate@example.com","role":"product_manager","productScopeMode":"selected_products","selectedProductIds":[23794]}'

SoundSync

Update scope and accept an invitation

Member update body
{"role":"analyst","productScopeMode":"selected_products","selectedProductIds":[23794]}
Acceptance body
{"token":"ONE_TIME_TOKEN_FROM_EMAIL"}
Error response shape (illustrative)
{"code":"developer_team_product_scope_invalid","message":"Selected-product members require at least one product.","field":"selectedProductIds"}

SoundSync

Handle errors without widening access

Status / codeRecovery
400 / invalid role, email or product scopeCorrect the indicated field; selected products must belong to the workspace.
401 / authentication or revoked sessionSign in again. Do not retry with an owner token on behalf of a denied member.
403 / permission, self-modification or invitation email mismatchCheck the signed-in account and allowed role. Do not bypass the denial.
404 / invitation or member not foundReload the workspace list; IDs are workspace-scoped.
409 / existing member, used invitation or last ownerRefresh current state; retain at least one active owner.
410 / invitation expired or revokedAsk an authorized member for a new invitation.
429 / rate limitWait before retrying. Do not repeatedly submit invitations.

Rate limits and response evidence

Default mutation limit: 30 requests per minute per user. Invitation acceptance: 20 per 15 minutes per user. Deployments may configure these limits. Fields and examples are traced to the current routes and service; they are not a production invitation test or a guarantee of email delivery.