Projects
A workspace is who you are: it holds your identity, your members, your plan, and one invoice. A project is where work happens inside it. A project groups the resources you create in it and the spend you incur from it, so a workspace can run several environments or several end customers without splitting into several accounts.
Every workspace has an implicit Default project. It is not a row you create or delete: any resource with no project lives there, which is where everything sits until you make your first project.
A project is a filter and a grouping, not a security boundary. It scopes what a credential may reach, what a scoped member sees, and where spend lands. If you need one team to be unable to see another team’s data at all, use a separate workspace.
Creating a project
cURL
Names are unique per workspace, case-insensitively. A workspace holds at most 100 live projects;
at the cap the create is refused with 409 project_limit_reached.
What a project groups
A derived record keeps the project it was created in even if its agent later moves, because your usage grouping and your invoice already report it that way.
Every list endpoint that takes a project accepts a project_id query parameter. Omit it to get
everything you can reach, pass a proj_... id for one project, or pass the literal default for
resources that sit in the implicit Default project. On the lists whose rows can be shared across
the workspace instead of living in one project - credentials, webhook endpoints and cloned voices -
that literal is shared, because an absent project there means workspace-wide rather than Default.
cURL
Pinning a credential
An API key or a service account can be pinned to one project when you create it. A pinned credential reads and writes only inside that project, its requests are attributed to that project, and it is subject to that project’s limits.
The pin is fixed at creation and cannot be edited afterwards, so re-scoping means minting a new credential and retiring the old one. A credential with no pin is workspace-wide.
What a grant does
By default every workspace member sees the whole workspace. Granting a member a project narrows them to the projects they hold: from their first grant onward, they see and work in those projects only, in the console and through the API.
- A member with no grants anywhere is workspace-wide. That is the default state, not a gap.
- Removing a member’s last grant returns them to workspace-wide access. To narrow someone, grant them the projects they should keep rather than revoking everything.
- Owners and billing admins cannot be scoped: both already hold workspace-wide access that a project grant would contradict without narrowing anything.
- A pending invite can carry projects, so an invitee is scoped from the moment they accept.
cURL
Limits and capacity
A project can carry its own ceilings, each sitting under the workspace’s own plan limits so one project cannot consume the whole allowance:
A project limit bounds work; it does not split the bill. The invoice stays workspace-level, and per-project cost shows up as a grouping on the workspace usage breakdown.
Archiving a project
Archiving suspends a project without removing anything. From then on nothing new starts or bills
inside it: conversation and widget sessions, inbound and outbound calls, batch calls, test runs,
knowledge-base imports, and any synthesis or gateway request on a credential pinned to the project
are all refused with 409 project_archived. Work already in flight is left to finish.
Everything in the project stays readable and its configuration stays editable. Archiving is idempotent and reversible: unarchive the project and work resumes.
Deleting a project
Deleting runs in one of two modes.
Detach is the default. Only the grouping is removed, and every resource in the project moves to
the Default project. It is refused with 409 project_has_scoped_credentials while an API key,
service account, vault credential, webhook endpoint, member grant, or pending invite is scoped to
the project, because detaching any of those would silently widen it.
Purge removes the project together with its contents in one transaction. It is available only
on an archived project, so a teardown always has a state you can sit in and reverse first; a
live project is refused with 409 project_not_archived. A purge is recoverable for 30 days, after
which the project and its contents are permanently deleted.
cURL
A purge is refused while a phone number is still attached, while a member’s only grant is this project, or while a live invite carries only this project, since clearing either would widen that person to the whole workspace.
Both modes have a preview that reports what the delete would do without doing it: whether a purge is available right now, every row holding the project open and which mode each refuses, what a purge would remove, and the operational records it would keep.
Restoring a purged project
A purge is recoverable for 30 days. The project disappears from every list and read immediately and its name is freed for reuse, but the project and its resources are kept and permanently deleted only once the window closes.
List what is still recoverable with include_purged=true, the only read that returns a purged
project. Each row carries purged_at, and the restore deadline is that stamp plus 30 days; a
project past its window is never listed, because a restore would refuse it.
cURL
What comes back: the project and its resources - agents with their tests, knowledge bases, tools, and audio assets - exactly the rows the purge removed. A resource you had deleted yourself before the purge stays deleted. The project returns archived, the state it was purged from, so nothing dispatches or bills inside it until you unarchive it.
What does not come back, on purpose: every credential the purge revoked stays revoked and
every grant it cleared stays cleared. API keys and service accounts pinned to the project are not
re-issued, vault credentials and webhook endpoints scoped to it are not undeleted, and member
grants and pending-invite scopes are not restored. Bringing a credential or a grant back would
re-grant access somebody deliberately ended, so the response reports them under still_revoked
instead. Re-create the credentials and re-grant the members the project still needs.
A restore is refused with 409 project_not_purged when the project was never purged,
409 project_restore_window_expired once the 30 days have passed, and 409 project_name_taken
when another project has taken this one’s name since the purge - rename the project holding it,
then restore.
A purge is recoverable for 30 days, but a restore is not a full undo: it returns the project and its resources, while the credentials it revoked and the access it cleared stay that way. Preview a purge first, and read the list of records it keeps: a project teardown that reads as total and is not would be worse than none.
Promoting a project
Promoting copies one project’s configuration into another project in the same workspace: build in staging, promote to production, tear staging down.
Copied: agents with every setting, tool definitions, knowledge bases with their folders, audio assets, and the webhook endpoints scoped to the source. Never copied: vault credentials, API keys and service accounts, phone numbers and SIP trunks, conversations, callers, memories, call and test history, member grants, spend limits, and every secret. A copied item whose credential reference was cleared, whose secret was minted fresh, or whose name collided in the target is listed for you rather than silently half-configured.
What projects scope in SpeechifyAI Build
Build and Agents share one workspace, and projects apply to them differently. The short answer: projects scope what you build with Agents, they scope what everything costs, and in Build they scope the one thing you create there, a cloned voice. The public voice and model catalog stays workspace-wide.
Two consequences are worth stating plainly, because they are the ones most often misread:
- A project’s budget can stop a Build request that creates nothing inside the project. A synthesis or gateway call leaves no resource behind and is still attributed to, and bounded by, the project its key is pinned to. Per-project Build cost is a statement about your API traffic, not about your console use.
- The pin belongs to an API key, so a console session never carries one. Everything a person does in the Build UI is workspace-level spend, whichever project the console is showing, and a voice cloned from the console is shared with the whole workspace rather than filed in a project.
Cloned voices and projects
A voice clone created by a project-pinned credential is filed under that project alongside your workspace, and the project decides who is shown it:
- A clone with a project is listed for the callers who can reach that project: a credential pinned to it, a member granted it, and anyone whose access is workspace-wide. It is not in anyone else’s voice list.
- A clone with no project is shared with the whole workspace and listed for everyone in it, a project-pinned credential included. That is every clone made before projects, every clone made by an unpinned credential or from the console, and every consent-verified clone.
GET /v1/voicestakes aproject_idfilter: pass aproj_...id for one project’s clones, or the literalsharedfor the clones no project filed. It issharedrather thandefaultbecause a clone with no project is shared across the workspace rather than sitting in the Default project, the same way a workspace-wide credential is. The public voice catalog and the model catalog are returned whatever you filter by, because nobody created them in a project.
The scope you are showing changes which clones you see. It does not change where a charge lands: synthesis bills to the project pinned on the credential that made the request, and a console session carries no pin.
Filing a clone to a project scopes who is shown it, not who could ever reach your account. A project is not a security boundary: use a separate workspace when one team must not be able to see another’s data at all.
Managing projects
Projects are managed in the console under Settings → Workspace → Projects: create and rename them, set their limits, grant members access, archive and unarchive, preview and run a delete, and promote one project into another. The scope picker in the top bar chooses the workspace and the project the console is showing.