client.auth.whoami() -> ApiResponseAuthWhoamiOut
-
-
-
Return the resolved authentication context for the current credential.
Useful for verifying that a Bearer JWT or API key is valid and discovering which workspace and permission scopes it grants — call this first when debugging authentication issues or bootstrapping an SDK integration.
The
auth_kindfield indicates whether the credential is a session token (clerk) or a programmatic key (api_key). For API keys,workspace_idandapi_key_idare always populated; for session tokens,workspace_idreflects theX-Workspace-Idheader value (if present) andapi_key_idisnull. Thescopeslist is sorted and deduplicated.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.auth.whoami()
-
-
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.list_dictionary_entries(...) -> ApiListResponseDictionaryOut
-
-
-
List dictionary entries for a single locale in the current workspace.
Returns a paginated list of entries for the BCP-47
languagelocale specified via the?language=query parameter (required, e.g.ko-kr). UseGET /dictionary/searchinstead when you need to match by word text across multiple locales, orGET /dictionary/languagesto discover which locales have entries before filtering here.audio_urlon entries withmethod=recordedis a short-lived presigned URL — do not cache it across sessions.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.list_dictionary_entries( language="de-de", )
-
-
-
language:
ListDictionaryEntriesApiV1DictionaryGetRequestLanguage— BCP-47 language code, e.g. en-us, ko-kr
-
method:
typing.Optional[typing.List[DictionaryMethod]]— Filter by one or more entry methods. Repeat to OR:?method=spelled&method=recorded. Omit to return all methods.
-
sort:
typing.Optional[ListDictionaryEntriesApiV1DictionaryGetRequestSort]— Field to sort by.uses_countranks the most-applied entries first, useful for auditing high-impact corrections.
-
order:
typing.Optional[ListDictionaryEntriesApiV1DictionaryGetRequestOrder]— Sort direction.
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Page size (max 50).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.create_dictionary_entry(...) -> ApiResponseDictionaryOut
-
-
-
Create a pronunciation dictionary entry in the current workspace.
Dictionary entries teach the synthesis pipeline how to pronounce words that it would otherwise handle incorrectly — brand names, acronyms, technical terms, proper nouns, and foreign loanwords. Each entry is scoped to a single BCP-47 locale and is applied during workflow execution when that locale is the synthesis target.
Three methods are supported via the
methodfield:spelled— provide a phonetic respelling inpronunciation(e.g."Poh-doh-nohs").pronunciationis required for this method.recorded— attach a reference audio clip by supplying anupload_idfrom a completed/uploadsstaging upload with categorydictionary. The audio is copied to permanent storage on create; the upload slot is consumed and cannot be reused for a different entry.ipa— supply an IPA transcription inipa.pronunciationis optional as a human-readable gloss alongside the IPA.
Returns 409 if a
(word, language)pair already exists in the workspace. Requireseditorworkspace role and thedictionary:writescope.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.create_dictionary_entry( word="word", method="spelled", language="language", )
-
-
-
word:
str— The surface form of the word or phrase as it appears in a script.
-
method:
DictionaryMethod— Pronunciation method:spelled(phonetic respelling),recorded(reference audio clip), oripa(IPA transcription).
-
language:
str— BCP-47 locale this entry applies to (e.g.ko-kr). Case-insensitive; stored lowercase.
-
workspace_id:
typing.Optional[str]
-
description:
typing.Optional[str]— Optional human-readable note about the entry (e.g. context, source).
-
pronunciation:
typing.Optional[str]— Phonetic respelling. Required whenmethodisspelled.
-
upload_id:
typing.Optional[str]— ID of a completed staging upload (categorydictionary). Required whenmethodisrecorded; consumed on create.
-
ipa:
typing.Optional[str]— IPA transcription of the word. Supplied by the caller; automatic generation is a planned enhancement.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.search_dictionary_entries(...) -> ApiListResponseDictionaryOut
-
-
-
Search dictionary entries by word text across one or more locales.
Performs a case-insensitive substring match on the
wordfield. Optionally narrow to one or more BCP-47 locales by repeating?language=(OR logic). Omittinglanguagesearches across all locales in the workspace.Use
GET /dictionary(locale-scoped list) when you want the full entry list for a specific locale; use this endpoint when you need to find how a word is defined across languages or when the user is typing a search query.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.search_dictionary_entries( search="search", )
-
-
-
search:
str— Substring to match against thewordfield (case-insensitive).
-
sort:
typing.Optional[SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort]— Field to sort by.
-
order:
typing.Optional[SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder]— Sort direction.
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Page size (max 50).
-
language:
typing.Optional[typing.List[SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem]]— Repeat for OR, e.g. ?language=en-us&language=ko-kr
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.list_dictionary_languages(...) -> ApiResponseListDictionaryLanguageOut
-
-
-
Return all locales that have at least one dictionary entry, with entry counts.
Results are ordered by entry count descending, then BCP-47 locale code ascending. Use this endpoint to populate a locale filter dropdown before calling
GET /dictionary?language=, rather than hard-coding the supported locale list in your client.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.list_dictionary_languages()
-
-
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.suggest_pronunciation(...) -> ApiResponsePronunciationSuggestion
-
-
-
Generate a pronunciation suggestion for a word before saving it as a dictionary entry.
Returns a
pronunciationstring suitable for use as thepronunciationfield when creating aspelled-method dictionary entry. The suggestion is deterministic (same word always returns the same result) and is intended as a starting point for human review, not as a production-ready transcription.languageis accepted to maintain a consistent request shape for future per-locale phonetic rules; it does not affect the current output.ipais alwaysnullin this version — automatic IPA generation is a planned enhancement.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.suggest_pronunciation( word="word", language="language", )
-
-
-
word:
str— The word or phrase to generate a pronunciation suggestion for.
-
language:
str— BCP-47 locale of the word. Reserved for future per-locale phonetic rules; does not affect current output.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.update_dictionary_entry(...) -> ApiResponseDictionaryOut
-
-
-
Update fields on an existing dictionary entry in the current workspace.
Supports partial updates — only the fields included in the request body are changed; omitted fields retain their current values. Passing
nullforword,method, orlanguageis rejected with 422, as these fields are required on the stored entry.To replace the reference audio on a
recorded-method entry, supply a newupload_idpointing to a completed staging upload. The previous audio is orphaned (not deleted from storage) and the new file is copied to permanent storage atomically.Returns 409 if the new
(word, language)combination already exists in the workspace. Requireseditorworkspace role and thedictionary:writescope.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.update_dictionary_entry( entry_id="entry_id", )
-
-
-
entry_id:
str
-
workspace_id:
typing.Optional[str]
-
word:
typing.Optional[str]— Updated surface form. Omit to leave unchanged.
-
description:
typing.Optional[str]— Updated human-readable note. Omit to leave unchanged.
-
pronunciation:
typing.Optional[str]— Updated phonetic respelling. Required when changingmethodtospelled.
-
upload_id:
typing.Optional[str]— New staging upload ID to replace the reference audio. Required when changingmethodtorecorded.
-
method:
typing.Optional[DictionaryMethod]— Updated pronunciation method. Omit to leave unchanged.
-
language:
typing.Optional[str]— Updated BCP-47 locale. Omit to leave unchanged.
-
ipa:
typing.Optional[str]— Updated IPA transcription. Omit to leave unchanged; supplynullexplicitly to clear.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.dictionary.delete_dictionary_entry(...) -> ApiResponseDict
-
-
-
Delete a dictionary entry from the current workspace.
The entry is removed from the workspace's dictionary and will no longer influence synthesis output in subsequent workflow runs. The operation is not reversible via the API — create a new entry to restore the pronunciation. Returns an empty
dataobject on success. Requireseditorworkspace role and thedictionary:writescope.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.dictionary.delete_dictionary_entry( entry_id="entry_id", )
-
-
-
entry_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.nodes.list_nodes() -> ApiListResponseNodePortsOut
-
-
-
List all available node types with their input/output port schemas.
Returns the static structural definition for every node type registered in the catalog — what ports each node exposes, their names, and expected data shapes — without runtime-variable values such as available languages or the TTS model catalog. This endpoint requires no
X-Workspace-Idheader and no authentication, making it suitable for static documentation generation and canvas layout tooling.For the full runtime configuration options a user would pick when wiring up a specific node (available target languages, provider/model options, voice picker URL), use
GET /api/v2/nodes/{node_type}instead.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.nodes.list_nodes()
-
-
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.nodes.get_node_detail(...) -> ApiResponseNodeDetailOut
-
-
-
Return full node definition and runtime configuration options for a node type.
Deprecated: use
GET /api/v2/nodes/{node_type}instead. This v1 variant inlines the full TTS model catalog underoptions.models_by_provider, which creates a large response and couples clients to the catalog structure. The v2 endpoint replaces that inline tree with aprovidersHATEOAS href pointing to the standalone/api/v1/providerscatalog, so the model list is fetched lazily only when needed.Unlike
GET /nodes(which returns only static port schemas), this endpoint returns the runtime values a caller uses to configure a node: supported target languages derived from deployment settings, the available model catalog, and a HATEOAS link to the workspace-scoped voice list. RequiresX-Workspace-Id.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.nodes.get_node_detail( node_type="node_type", )
-
-
-
node_type:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.nodes.get_node_detail_v2(...) -> ApiResponseNodeDetailOut
-
-
-
Return full node definition and runtime configuration options for a node type (v2).
Extends
GET /api/v1/nodes/{node_type}by replacing the large inline model catalog (options.models_by_provider) with aprovidersHATEOAS href pointing toGET /api/v1/providers. Clients follow that link to load the model list and each model's configuration schema only when the user opens the relevant configuration panel, rather than receiving it in every node-detail response.The
voicesHATEOAS href (with its provider, model, and language filter parameters) is unchanged from v1, so the voice picker does not require a catalog call. Supported target languages are resolved from deployment settings at request time. RequiresX-Workspace-Idand thecatalog:readscope.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.nodes.get_node_detail_v2( node_type="node_type", )
-
-
-
node_type:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.providers.list_catalog_providers(...) -> ApiListResponseCatalogProviderOut
-
-
-
List all available speech synthesis providers in the catalog.
Returns the full set of processing providers — each with its display name, number of available models, and a HATEOAS
modelslink toGET /providers/{provider}/models. The response contains only customer-facing metadata; cost, credentials, and base URLs are never included.This endpoint is the starting point for building a provider/model/voice selection flow. The typical traversal is: list providers → follow
modelslink → followvoiceslink for the chosen model. RequiresX-Workspace-Idand thecatalog:readscope.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.providers.list_catalog_providers()
-
-
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.providers.get_catalog_provider(...) -> ApiResponseCatalogProviderOut
-
-
-
Get a single speech synthesis provider by its canonical identifier.
Returns the same shape as an item in
GET /providers— display name, model count, and a HATEOASmodelslink — but scoped to a single provider. Returns 404 if the provider identifier is not recognized. The canonical identifier is the lowercase slug returned in theproviderfield of the list response.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.providers.get_catalog_provider( provider="provider", )
-
-
-
provider:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.providers.list_catalog_provider_models(...) -> ApiListResponseCatalogModelOut
-
-
-
List all models available for a given provider.
Returns each model's display name, content type, live
voice_count(the number of platform voices catalogued under that model), and acontrolsmap describing the canonical provider-agnostic parameters supported by the model (e.g. speed, stability). Also includesconfig_schemafor back-compat — new integrations should prefercontrolsas the authoritative parameter description. Each item includes a HATEOASvoiceslink to the paginated voice list for that model. Returns 404 if the provider is not recognized.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.providers.list_catalog_provider_models( provider="provider", )
-
-
-
provider:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.providers.list_catalog_provider_model_voices(...) -> ApiCountedListResponseCatalogVoiceOut
-
-
-
List platform voices available for a specific provider and model.
Returns a paginated list of voices from the platform catalog (system workspace) that declare support for the given
model. A voice can appear under multiple models when itssupported_modelslist includes more than one entry; voices with no supported models are excluded from all model listings.Each voice includes gender, age, accent, supported locales, and a short-lived presigned
preview_urlfor the audio sample — do not cache these URLs across sessions. The responsepagination.totalfield reflects the total match count for the provider/model pair.For the workspace voice picker (which merges platform and workspace-scoped voices and supports favorite/similarity filtering), use
GET /voiceswith?provider=and?model=query parameters instead.Returns 404 if the provider or model is not recognized.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.providers.list_catalog_provider_model_voices( provider="provider", model="model", )
-
-
-
provider:
str
-
model:
str
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Page size (max 100).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.providers.get_catalog_provider_model(...) -> ApiResponseCatalogModelOut
-
-
-
Get a single model for a given provider.
Returns the same shape as an item in
GET /providers/{provider}/models, includingcontrols(canonical parameter map),config_schema(for back-compat), livevoice_count, and a HATEOASvoiceslink. Returns 404 if the provider or model identifier is not recognized.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.providers.get_catalog_provider_model( provider="provider", model="model", )
-
-
-
provider:
str
-
model:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.list(...) -> ApiListResponseTemplateOut
-
-
-
Browse the public template gallery across all workspaces.
Returns only templates that have an active published snapshot (
is_public=true,published_definitionset, not unpublished). Results come from any workspace — the gallery is intentionally cross-workspace so callers can discover shared starting points regardless of their own workspace membership.Does not require
X-Workspace-Id, so callers without a workspace (e.g. during onboarding) can still browse. The response reflects the published snapshot for each row, not any unpublished draft edits.Dual-auth: Bearer JWT or API key (scope
templates:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.list()
-
-
-
category:
typing.Optional[typing.List[TemplateCategory]]— Filter by category. Repeat the parameter for OR logic, e.g.?category=media&category=creative.
-
search:
typing.Optional[str]— Full-text search over template name and description.
-
sort:
typing.Optional[ListTemplatesRequestSort]— Sort order:recent(last published),popular(most cloned), orname(alphabetical).
-
offset:
typing.Optional[int]— Zero-based offset for page navigation.
-
limit:
typing.Optional[int]— Maximum number of templates to return (1–100).
-
favorites_only:
typing.Optional[bool]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.create_template(...) -> ApiResponseTemplateOut
-
-
-
Create a reusable workflow template in the current workspace.
Templates are workspace-private on creation (
is_public=false,is_starter=false). The fullWorkflowDefinition(graph + execution config) is validated at write time — structural errors (duplicate node/edge IDs, port mismatches, etc.) surface here rather than when a caller later clones the template into a workflow.Use this to capture a workflow configuration you intend to reuse or share. To make a template available in the public gallery, an admin must mark it public via the admin API. To create a runnable workflow from an existing template, use
POST /templates/{id}/cloneinstead.Requires workspace
editorrole or higher.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.create_template( name="name", )
-
-
-
name:
str— Display name for the template (1–200 characters, not blank).
-
workspace_id:
typing.Optional[str]
-
description:
typing.Optional[str]— Optional human-readable description shown in the gallery (max 2,000 characters).
-
category:
typing.Optional[TemplateCategory]— Optional category tag used for gallery filtering.
-
definition:
typing.Optional[WorkflowDefinitionInput]— Full workflow definition (graph + execution config). Validated at write time — structural errors are rejected with 422.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.get(...) -> ApiResponseTemplateOut
-
-
-
Fetch a single template by ID.
Returns the template if it is visible to the caller: templates owned by the caller's workspace are returned with the live draft definition; public/starter templates from other workspaces are returned with the published snapshot.
Returns 404 for templates that exist but are not visible to the caller (not owned, not public, not a starter) — same response as for a missing ID.
Dual-auth: Bearer JWT or API key (scope
templates:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.get( template_id="template_id", )
-
-
-
template_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.delete_template(...) -> ApiResponseDict
-
-
-
Delete a template owned by the caller's workspace.
The delete is a soft delete — the record is hidden from the gallery and all visibility checks immediately, but is not physically removed. Any workflows previously cloned from this template are unaffected; clone creates an independent copy of the definition at clone time.
Restrictions:
- Only the owning workspace may delete its templates (403 otherwise).
- Platform starter templates (
is_starter=true) cannot be deleted (403).
Requires workspace
editorrole or higher.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.delete_template( template_id="template_id", )
-
-
-
template_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.update_template(...) -> ApiResponseTemplateOut
-
-
-
Update a template owned by the caller's workspace.
All fields are optional (omit to keep the stored value). When
definitionis supplied it is a full replace — send the complete graph, not a partial diff. Structural validation runs on write, same asPOST /templates.Restrictions:
- Only the owning workspace may update its templates (403 otherwise).
- Platform starter templates (
is_starter=true) are read-only via this endpoint regardless of workspace ownership (403). - Updates apply only to the draft/live definition; the published gallery snapshot is not updated until an admin republishes.
Requires workspace
editorrole or higher.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.update_template( template_id="template_id", )
-
-
-
template_id:
str
-
workspace_id:
typing.Optional[str]
-
name:
typing.Optional[str]
-
description:
typing.Optional[str]
-
category:
typing.Optional[TemplateCategory]
-
definition:
typing.Optional[WorkflowDefinitionInput]— Full-replace on PATCH. Omit to keep the stored value. Explicitnullis rejected — there is no 'empty graph' use-case worth the ambiguity. The union withnullhere only makes omission easy for FE clients; seereject_null_definitionfor the runtime guard.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.estimate_template(...) -> ApiResponseTemplateEstimateResponse
-
-
-
Estimate the credit cost of running a workflow built from this template.
Returns a per-unit pricing guide expressed in credits per
unit_charsinput characters (default 1,000). Because the template does not contain the caller's actual script, the estimate uses a synthetic fixed-length input to compute a reproducible per-unit rate. Multiply by your expected character count to project total cost.The response distinguishes variable costs (scale with script length, e.g. synthesis) from fixed costs (apply once per run regardless of length). A node-level breakdown is included so callers can see which processing steps drive the cost.
Results are cached against the template definition and current pricing rates.
cache_statusindicates whether this response was served from cache (hit), computed fresh (miss), or recomputed because the definition or rates changed (stale).Visibility rules match
GET /templates/{id}— own-workspace templates use the draft definition; cross-workspace templates use the published snapshot.Dual-auth: Bearer JWT or API key (scope
templates:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.estimate_template( template_id="template_id", )
-
-
-
template_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.clone(...) -> ApiResponseWorkflowOut
-
-
-
Create a runnable workflow in the caller's workspace from a template.
This is the primary way to use a template: it produces a new
Workflowowned by the caller's workspace, ready to accept scripts and run jobs.Use
body.nameto set the workflow name; omit it (or send blank/whitespace) to get the default"{template name} (Copy)".Cross-workspace clones (gallery/starter templates) copy the published snapshot so unpublished draft edits made by the template owner never leak to other workspaces. Same-workspace clones copy the live draft definition.
Use
GET /templates/{id}/estimatefirst to preview credit costs before committing to a clone and run. UsePOST /workflows/{id}/duplicateto copy an existing workflow rather than starting from a template.Requires workspace
editorrole or higher. Dual-auth: Bearer JWT or API key (scopeworkflows:write).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.clone( template_id="template_id", )
-
-
-
template_id:
str
-
workspace_id:
typing.Optional[str]
-
name:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.favorite_template(...) -> ApiResponseTemplateOut
-
-
-
Add a template to the current user's favorites.
Favorites are per-user, not per-workspace — the same favorite list is visible regardless of which workspace the caller is currently acting in. Any template visible to the caller (own workspace, public, or starter) can be favorited.
Returns 404 when the template does not exist or is not visible to the caller. Calling this endpoint on an already-favorited template is idempotent (returns 200 with the template). Use
DELETE /templates/{id}/favoriteto remove. Does not requireX-Workspace-Id.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.favorite_template( template_id="template_id", )
-
-
-
template_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.templates.unfavorite_template(...) -> ApiResponseDict
-
-
-
Remove a template from the current user's favorites.
Idempotent and non-enumerating: returns an empty success response whether or not the favorite or the template exists. Does not require
X-Workspace-Id.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.templates.unfavorite_template( template_id="template_id", )
-
-
-
template_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.list(...) -> ApiCountedListResponseVoiceOut
-
-
-
List TTS voices available to the current workspace.
Every filter accepts repeat-key OR semantics:
?gender=female&gender=neutral&category=narration&source=platform&source=workspace. Filters combine across fields with AND; within a field, values OR.languagematches a voice when any of its declared locales matches any requested value. Platform voices with no declared locales (catalog gaps) are treated as general-use and match every language filter. User-uploaded / cloned voices with no declared locales are excluded — that state means "language unknown" pending the clone flow's language detection.Multi-sort:
sortandorderare parallel lists.?sort=uses_count&sort=name&order=desc&order=ascorders primarily by uses_count DESC, secondarily by name ASC. Whenorderis shorter thansort, missing entries default per-field:name=asc, created_at=desc, uses_count=desc. Whensortis omitted, list defaults to newest-first (or most-recently-favorited-first iffavorites_only=true). Every sort path appendsVoice.id ASCas a deterministic tiebreaker for pagination stability.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.list()
-
-
-
offset:
typing.Optional[int]— Number of results to skip for pagination.
-
limit:
typing.Optional[int]— Maximum number of results to return (1–100).
-
favorites_only:
typing.Optional[bool]— When true, return only voices in the workspace's favorites list.
-
source:
typing.Optional[typing.List[ListVoicesRequestSourceItem]]— Repeat for OR across scopes:platformfor system-provided voices,workspacefor workspace-owned voices.
-
gender:
typing.Optional[typing.List[VoiceGender]]— Repeat for OR
-
age:
typing.Optional[typing.List[VoiceAge]]— Repeat for OR
-
category:
typing.Optional[typing.List[VoiceCategory]]— Repeat for OR
-
accent:
typing.Optional[typing.List[VoiceAccent]]— Repeat for OR
-
search:
typing.Optional[str]— Full-text search against voice name, description, and tags.
-
sort:
typing.Optional[typing.List[ListVoicesRequestSortItem]]— Repeat for multi-sort. Pairs withorderindex-wise.
-
order:
typing.Optional[typing.List[ListVoicesRequestOrderItem]]— Parallel to sort[]; shorter is padded with per-field defaults.
-
provider:
typing.Optional[typing.List[ListVoicesRequestProviderItem]]— Repeat for OR, e.g. ?provider=elevenlabs&provider=rime
-
model:
typing.Optional[typing.List[str]]— Repeat for OR. Filters platform voices by TTS model, e.g. ?model=arcana&model=sonic-2
-
language:
typing.Optional[typing.List[ListVoicesRequestLanguageItem]]— Repeat for OR, e.g. ?language=en-us&language=ko-kr
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.get_voice_facets(...) -> ApiResponseVoiceFacetsOut
-
-
-
Filter-bar options (chips) for the voice browser, one list per dimension.
Returns
providers,models,languages(data-driven) plusgenders,ages,categories,accents(fixed enums) asVoiceFacetItem[]so the FE builds the whole filter bar — with per-chip count badges — in a single request instead of hardcoding option lists (mirrorsGET /dictionary/languages). Each item is{value, label, count}:valueis passed straight back toGET /voices;labelis the display name for providers/models andnullelsewhere (the FE owns language + enum labels);countis the number of matching voices. Forlanguages/models,countcounts only voices that explicitly declare the value — "general-use" platform voices (no declared locales/models) thatGET /voicesmatches against every language/model filter are not counted, so a chip's count can be lower than theGET /voicesresult.Accepts the SAME filters as
GET /voices(tab scopesource/favorites_only, plusprovider/model/language/gender/age/category/accent/search).countis context-aware (faceted search): each dimension's counts apply every OTHER active filter but exclude that dimension's own selection — e.g. withprovider=elevenlabsthe language counts are scoped to ElevenLabs, while the provider chips still show every provider so the caller can switch.Count-0 policy: data-driven dimensions omit count-0 values (only present ones, each a valid
GET /voicesfilter — providers/models restricted to the enabled catalog, languages to the supported-locale allowlist, so a chip never 422s). Enum dimensions always return the full enum in natural order, count-0 included, for the FE to grey out.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.get_voice_facets()
-
-
-
favorites_only:
typing.Optional[bool]— Favorites tab scope
-
source:
typing.Optional[typing.List[GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem]]— Tab scope — repeat for OR, same values as GET /voices (e.g. platform, workspace)
-
gender:
typing.Optional[typing.List[VoiceGender]]— Repeat for OR
-
age:
typing.Optional[typing.List[VoiceAge]]— Repeat for OR
-
category:
typing.Optional[typing.List[VoiceCategory]]— Repeat for OR
-
accent:
typing.Optional[typing.List[VoiceAccent]]— Repeat for OR
-
search:
typing.Optional[str]
-
provider:
typing.Optional[typing.List[str]]— Repeat for OR, e.g. ?provider=elevenlabs&provider=rime
-
model:
typing.Optional[typing.List[str]]— Repeat for OR. Filters platform voices by TTS model, e.g. ?model=arcana&model=sonic-2
-
language:
typing.Optional[typing.List[str]]— Repeat for OR, e.g. ?language=en-us&language=ko-kr
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.get(...) -> ApiResponseVoiceOut
-
-
-
Fetch a single voice by its ID.
Returns both platform (system-wide) voices and voices that belong to the caller's workspace. Returns 404 when the voice does not exist or is not accessible to the caller's workspace. The
sample_urlfield is a time-limited presigned URL valid for 1 hour; regenerate it by calling this endpoint again rather than caching it long-term.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.get( voice_id="voice_id", )
-
-
-
voice_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.similar(...) -> ApiListResponseVoiceSimilarOut
-
-
-
Return voices acoustically similar to a reference voice.
Results are ranked by semantic similarity score (descending) and include the reference voice's workspace voices and all platform voices. Each result includes a
similarity_scorebetween 0 and 1. Optionally filter by one or morelanguageBCP-47 codes (repeat the parameter for OR semantics); up to 16 language values are accepted. Returns 503 when the reference voice has no embedding yet — retry after the indicatedRetry-Afterinterval. Prefer this endpoint overGET /voiceswith manual filtering when building a "voices like this" recommendation UI.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.similar( voice_id="voice_id", )
-
-
-
voice_id:
str
-
limit:
typing.Optional[int]— Number of similar voices to return (1–50).
-
language:
typing.Optional[typing.List[str]]— Repeat for OR, e.g. ?language=en-us&language=ko-kr
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.favorite_voice(...) -> ApiResponseVoiceOut
-
-
-
Add a voice to the current workspace's favorites.
Favorites are workspace-scoped, not per-user: all members of the workspace see the same favorited set. Idempotent — favoriting a voice that is already favorited succeeds without error. Returns the voice with
is_favorite=true. Requires the caller to have at least editor role in the workspace.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.favorite_voice( voice_id="voice_id", )
-
-
-
voice_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.voices.unfavorite_voice(...) -> ApiResponseDict
-
-
-
Remove a voice from the current workspace's favorites.
Idempotent — removing a voice that is not currently favorited succeeds without error. Requires the caller to have at least editor role in the workspace.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.voices.unfavorite_voice( voice_id="voice_id", )
-
-
-
voice_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace.get_workspace_settings(...) -> ApiResponseWorkspaceSettingsOut
-
-
-
Return workspace-level settings for the specified workspace.
Currently exposes
default_language(the locale used as the default for new workflow nodes) andtheme(the workspace's display color theme). Settings are workspace-scoped: all members of the workspace share the same values. Per-user preferences (e.g. personal dark mode) are outside the scope of this endpoint.If settings have not yet been explicitly configured for the workspace, defaults are returned (and persisted) on first access.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace.get_workspace_settings( ws_id="ws_id", )
-
-
-
ws_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.list_members(...) -> ApiListResponseWorkspaceMemberOut
-
-
-
List active members and pending invites for a workspace.
Returns a unified list combining confirmed members (status
active) and outstanding invites that have not yet been accepted or revoked (statusinvited). Pending invites appear withuser_id: nulland only theemailandrolefields populated.The list is sorted: the requesting user appears first, then admins by join date, then other members by join date. No pagination — the full roster is returned in a single response.
Roles:
admin: can manage members, invites, workspace settings, and all content.editor: can create, edit, and run workflows; cannot manage members.viewer: read-only access to workspace content and run history.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.list_members( ws_id="ws_id", )
-
-
-
ws_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.create_invite(...) -> ApiResponseWorkspaceInviteOut
-
-
-
Invite a user to the workspace by email. Admin only.
Creates a pending invite and sends an invitation email to the specified address. The invitee does not need to have an existing account — they can sign up after receiving the invite. The invite includes a role (
admin,editor, orviewer) that the invitee will receive upon accepting.Invites expire after 14 days. Only one pending invite per email address per workspace is allowed at a time; re-inviting the same address while a pending invite exists returns 409. Inviting an address that already belongs to an active member also returns 409.
The total number of active members plus pending invites is counted against the workspace owner's plan seat limit. Exceeding the limit returns 402. The invitee's role can be updated before acceptance via
PATCH /workspaces/{ws_id}/invites/{invite_id}, or the invite can be cancelled viaDELETE /workspaces/{ws_id}/invites/{invite_id}.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.create_invite( ws_id="ws_id", email="email", role="admin", )
-
-
-
ws_id:
str
-
email:
str— Email address to invite. Normalized to lowercase. Returns 409 if this address is already an active member or has a pending invite.
-
role:
WorkspaceRole— Role to grant when the invite is accepted:admin,editor, orviewer.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.remove_member(...) -> ApiResponseDict
-
-
-
Remove an active member from the workspace. Admin only.
The removed member immediately loses access to all workspace resources. They receive an email notification informing them they have been removed.
Two protections prevent accidental lockouts:
- The workspace owner cannot be removed.
- The last remaining admin cannot be removed (returns 409).
Removing a member does not affect their account or other workspaces. To block an invited but not-yet-accepted user instead, revoke the invite via
DELETE /workspaces/{ws_id}/invites/{invite_id}.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.remove_member( ws_id="ws_id", member_id="member_id", )
-
-
-
ws_id:
str
-
member_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.update_member_role(...) -> ApiResponseDict
-
-
-
Change a workspace member's role. Admin only.
Updates the role of an active member to
admin,editor, orviewer. The operation is idempotent — setting a member to their current role succeeds silently (no error, no duplicate email notification).Two protections prevent accidental lockouts:
- The workspace owner's role cannot be changed.
- The last remaining admin cannot be demoted (returns 409).
When the role actually changes, the affected member receives an email notification describing their new permissions.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.update_member_role( ws_id="ws_id", member_id="member_id", role="admin", )
-
-
-
ws_id:
str
-
member_id:
str
-
request:
WorkspaceMemberRoleUpdate
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.revoke_invite(...) -> ApiResponseDict
-
-
-
Cancel a pending invite so the invitee can no longer accept it. Admin only.
The invite token is invalidated immediately. If the invitee attempts to accept after revocation, they receive a 410 Gone. The invite is removed from the pending list returned by
GET /workspaces/{ws_id}/members.Revoking an invite that is already accepted, revoked, or expired returns 404. To remove an already-accepted member, use
DELETE /workspaces/{ws_id}/members/{member_id}.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.revoke_invite( ws_id="ws_id", invite_id="invite_id", )
-
-
-
ws_id:
str
-
invite_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.update_invite_role(...) -> ApiResponseWorkspaceInviteOut
-
-
-
Change the role on a pending (not yet accepted) invite. Admin only.
Updates the role the invitee will receive when they accept. Only pending invites can be updated — attempting to update an accepted, revoked, or expired invite returns 409. The invitee is not notified of the role change; the updated role takes effect when they accept.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.update_invite_role( ws_id="ws_id", invite_id="invite_id", role="admin", )
-
-
-
ws_id:
str
-
invite_id:
str
-
request:
WorkspaceMemberRoleUpdate
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspace_members.accept_invite(...) -> ApiResponseDict
-
-
-
Accept a workspace invite using the token from the invitation email.
The
tokenpath parameter comes from the invitation link sent to the invitee's email. The caller must be authenticated and their verified email address must match the address the invite was sent to (403 if it does not).On success the caller is added to the workspace with the role specified in the invite, and
workspace_idis returned so the caller can immediately begin using that workspace. If the caller is already a member of the workspace (e.g. accepted via a different device), the accept is idempotent and returns the sameworkspace_id.Error cases (all return 410 Gone):
- Invite already accepted.
- Invite was revoked by an admin.
- Invite has expired (14-day TTL from creation).
The workspace owner's plan seat limit is re-checked at accept time in case the plan was downgraded after the invite was sent; exceeding the limit returns 402.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspace_members.accept_invite( token="token", )
-
-
-
token:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.list_workspaces(...) -> ApiListResponseWorkspaceOut
-
-
-
List all workspaces the current user is a member of.
Returns workspaces where the caller has any role (admin, editor, or viewer), including workspaces they own and workspaces they joined via invite. Results are paginated; omits soft-deleted workspaces and the internal system workspace.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.list_workspaces()
-
-
-
offset:
typing.Optional[int]
-
limit:
typing.Optional[int]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.create_workspace(...) -> ApiResponseWorkspaceOut
-
-
-
Create a new workspace owned by the current user.
Workspaces are the top-level container for all resources (workflows, voices, dictionary entries, members). Every resource is scoped to exactly one workspace via the
X-Workspace-Idheader on subsequent requests.The authenticated user becomes the workspace owner and is automatically added as an
adminmember. An optionalslug(1–50 characters, lowercase kebab-case) can be supplied for a human-readable workspace identifier; if omitted, one is auto-generated fromname. Returns 409 if the slug is already taken, 422 if the slug format is invalid or uses a reserved word.The number of workspaces a user may own is plan-gated. Attempting to exceed the limit returns 402.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.create_workspace( name="name", )
-
-
-
name:
str— Human-readable workspace name (1–200 characters, non-blank).
-
slug:
typing.Optional[str]— Optional URL-safe identifier (lowercase kebab-case, 1–50 characters). Auto-generated fromnameif omitted. Returns 409 if taken, 422 if invalid or reserved.
-
color_idx:
typing.Optional[int]— Index into the workspace color palette (0–6).
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.slug_available(...) -> ApiResponseSlugAvailabilityOut
-
-
-
Check whether a slug is available for the current workspace. Admin only.
Returns
{ available: true }if the slug is valid, not reserved, and not already claimed by another workspace. When unavailable,reasonindicates why:invalid(format/length),reserved(blocked word), ortaken(already in use globally). The workspace's own current slug is self-excluded, so an admin can safely check their existing slug without receivingtaken.This is an advisory point-in-time check — a concurrent
POST /workspacesorPATCH /workspaces/{id}from another session can claim the slug between this response and the caller's write. Always handle 409WORKSPACE_SLUG_TAKENoncreate_workspaceandupdate_workspace.Requires the
X-Workspace-Idheader (the workspace being renamed) and admin role in that workspace. Missing/invalid header returns 400; not a member returns 404; not admin returns 403.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.slug_available( slug="slug", )
-
-
-
slug:
str— Candidate slug; normalized (strip().lower()) before checks.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.get_workspace(...) -> ApiResponseWorkspaceOut
-
-
-
Fetch a single workspace by ID.
Returns the workspace if the current user is an active member (any role). Returns 404 if the workspace does not exist, has been deleted, or the caller is not a member — the two cases are intentionally indistinguishable to prevent workspace enumeration.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.get_workspace( workspace_id="workspace_id", )
-
-
-
workspace_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.delete_workspace(...) -> ApiResponseDict
-
-
-
Delete a workspace and all of its resources. Owner only.
Soft-deletes the workspace and cascades to all owned resources (workflows, voices, dictionary entries, members, etc.). The workspace and its contents become inaccessible via the API immediately. Data is retained for the GDPR retention period before permanent purge.
Only the workspace owner (the user who created it) can delete it; admin members who are not the owner receive 404. Returns 404 if the workspace does not exist or the caller is not the owner.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.delete_workspace( workspace_id="workspace_id", )
-
-
-
workspace_id:
str
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workspaces.update_workspace(...) -> ApiResponseWorkspaceOut
-
-
-
Update a workspace's name, color palette index, and/or slug. Admin only.
All fields are optional — supply only the fields you want to change.
slugfollows the same validation rules as on create (lowercase kebab-case, 1–50 characters, no reserved words). Returns 409 if the new slug is already claimed by another workspace, 422 if the slug format is invalid or reserved. Re-setting the workspace's current slug to itself never returns 409.Only workspace admins may call this endpoint; other members receive 404 (same as not-found, to avoid leaking membership details to non-members).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workspaces.update_workspace( workspace_id="workspace_id", )
-
-
-
workspace_id:
str
-
name:
typing.Optional[str]— New workspace name. Omit to leave unchanged.
-
slug:
typing.Optional[str]— New slug (lowercase kebab-case, 1–50 characters). Omit to leave unchanged. Returns 409 if taken, 422 if invalid or reserved.
-
color_idx:
typing.Optional[int]— New color palette index (0–6). Omit to leave unchanged.
-
routing_price_sensitivity:
typing.Optional[float]— New voice-selection price/quality balance (0.0 = pure quality, 1.0 = pure price, 0.5 = balanced). Omit to leave unchanged.
-
routing_llm_fit:
typing.Optional[bool]— New setting for whether automatic voice selection also weighs content fit. Omit to leave unchanged.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.uploads.create(...) -> ApiResponseUploadCreateResponse
-
-
-
Request a presigned URL to upload a file to object storage (step 1 of 2).
The two-step upload flow:
POST /uploads— register the file and receive a short-livedupload_url. PUT your file bytes directly to that URL (do not send them to this API).POST /uploads/{id}— confirm the upload completed and bind the file to a resource (e.g. a workflow). The file is moved to its final location and the upload record transitions frompendingtouploaded.
categorycontrols which file formats are accepted:script— text-based formats (txt, srt, csv, json, xliff, docx)dictionary— audio formats (mp3, wav, m4a, ogg, webm)
The presigned URL expires within a short window (see
upload_urlTTL in the response). If the URL expires before the PUT completes, discard this upload record and start over with a freshPOST /uploadscall.X-Workspace-Idis optional but recommended for workspace-scoped storage quota tracking. API keys with a bound workspace attach automatically.Dual-auth: Bearer JWT or API key (scope
uploads:write).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.uploads.create( filename="filename", category="script", )
-
-
-
filename:
str— Original filename including extension (e.g.script.txt). Must include a file extension.
-
category:
UploadRequestCategory— File category. Determines which formats are accepted:scriptfor text formats (txt, srt, csv, json, xliff, docx);dictionaryfor audio formats (mp3, wav, m4a, ogg, webm).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.uploads.confirm(...) -> ApiResponseUploadOut
-
-
-
Confirm a completed upload and bind it to a resource (step 2 of 2).
Call this after successfully PUTting your file to the presigned URL returned by
POST /uploads. Providecontext_typeandcontext_idto associate the file with an existing resource (currentlyworkflowis the supported context type). The file is moved to its final location andstatustransitions frompendingtouploaded.This endpoint is idempotent: if the upload was already confirmed, the current state is returned without re-processing.
Storage quota is checked against the workspace at confirm time. If confirming would exceed the workspace storage limit, a 402 is returned and the file remains in its staging location (the upload record stays
pendingso you can delete the staging file and try a smaller file).Binding to a workspace-scoped resource requires the caller to be a member of that workspace. Workspace is inferred from the resource when
X-Workspace-Idis omitted.Dual-auth: Bearer JWT or API key (scope
uploads:write).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.uploads.confirm( upload_id="upload_id", context_type="workflow", context_id="context_id", )
-
-
-
upload_id:
str
-
context_type:
UploadConfirmRequestContextType— Type of resource this upload is being attached to. Currently onlyworkflowis supported.
-
context_id:
str— ID of the resource to attach this upload to. Must be an existing resource of the givencontext_typethat the caller has access to.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.uploads.delete(...) -> ApiResponseDict
-
-
-
Delete an upload and its associated file.
Permanently removes the upload record and schedules the stored file for deletion. The record is removed first; the file is cleaned up asynchronously after the response so storage removal only happens after a successful commit.
If the upload was previously confirmed against a workspace-scoped resource, the consumed storage bytes are released back to the workspace quota, keeping the workspace storage counter accurate.
Callers can delete uploads in any state (
pendingoruploaded). Deleting apendingupload (e.g. after an expired presigned URL) is the correct way to clean up an abandoned upload attempt.Dual-auth: Bearer JWT or API key (scope
uploads:write).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.uploads.delete( upload_id="upload_id", )
-
-
-
upload_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.usage.usage_summary(...) -> ApiResponseUsageSummaryOut
-
-
-
Return aggregated usage totals and activity chart data for the workspace.
Combines credit consumption, character and line counts, and workflow run statistics for the requested rolling window (
range) with a chart-ready activity series (activity) bucketed byactivity_view.The
credits.usedfield reflects the authenticated user's own billing-period consumption; all other aggregate fields (characters, lines, runs, daily buckets, activity buckets) are workspace-scoped across all members.Date boundaries are computed in the supplied
timezone(IANA, e.g.America/New_York) so "today" and "this week" align with the caller's local calendar. Defaults to UTC.Use
GET /usage/by-languagefor a language-level breakdown, orGET /usage/activityfor the event-by-event feed.Dual-auth: Bearer JWT or API key (scope
workspace:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.usage.usage_summary()
-
-
-
range:
typing.Optional[UsageSummaryApiV1UsageSummaryGetRequestRange]— Rolling local calendar-day range.
-
activity_view:
typing.Optional[UsageSummaryApiV1UsageSummaryGetRequestActivityView]— Activity chart view: daily=7 local days, weekly=12 Monday-start weeks, monthly=12 months.
-
timezone:
typing.Optional[str]— IANA timezone for local day bucketing.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.usage.usage_by_language(...) -> ApiResponseUsageByLanguageOut
-
-
-
Return workspace audio generation usage broken down by language.
Each row represents one locale with its share of total credit and character consumption.
shareis a 0..1 fraction of workspace-wide usage for the period; multiply by 100 for a percentage.Period selection: supply
activity_viewto align the language rows with the same period shown on the Usage dashboard chart (daily = last 7 local days, weekly = last 12 Monday-start weeks, monthly = last 12 months). Whenactivity_viewis provided,rangeis ignored andrangein the response isnull. Omitactivity_viewto use the rollingrangewindow instead.Date boundaries are computed in the supplied
timezone(IANA). Defaults to UTC.Dual-auth: Bearer JWT or API key (scope
workspace:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.usage.usage_by_language()
-
-
-
range:
typing.Optional[UsageByLanguageApiV1UsageByLanguageGetRequestRange]— Rolling local calendar-day range.
-
activity_view:
typing.Optional[UsageByLanguageApiV1UsageByLanguageGetRequestActivityView]— Optional activity view period to align language rows with the selected Usage tab. When supplied, range is ignored and range in the response is null.
-
timezone:
typing.Optional[str]— IANA timezone for local day bucketing.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.usage.usage_activity(...) -> ApiListResponseUsageActivityOut
-
-
-
Return the workspace activity feed as a cursor-paginated event list.
Each item represents a discrete workspace event (workflow run, voice generated, template applied, member invited, API key created, settings changed). Events are ordered newest-first within the requested rolling window.
Filtering:
typenarrows to a single action kind (e.g.workflow_run).user_idrestricts to events triggered by a specific workspace member; returns 404 if the user is not a member of this workspace.- Both filters can be combined.
Pagination: pass the
cursorvalue from a previous response to retrieve the next page. An absent or nullcursorin the response means no further pages exist. Page size is controlled bylimit(1–100, default 20).Date boundaries are computed in the supplied
timezone(IANA). Defaults to UTC.Dual-auth: Bearer JWT or API key (scope
workspace:read).
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.usage.usage_activity()
-
-
-
range:
typing.Optional[UsageActivityApiV1UsageActivityGetRequestRange]— Rolling local calendar-day range.
-
type:
typing.Optional[UsageActivityAction]— Filter by usage activity type.
-
user_id:
typing.Optional[str]— Filter by actor user id.
-
limit:
typing.Optional[int]
-
cursor:
typing.Optional[str]— Opaque pagination cursor.
-
timezone:
typing.Optional[str]— IANA timezone for local day bucketing.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.users.get_my_credits() -> ApiResponseBalanceResponse
-
-
-
Return the caller's current credit balance and billing period details.
balanceis the authoritative gate value: use it to decide whether to attempt a workflow run.remainingis a display convenience derived from settled ledger entries and may temporarily exceedbalancewhile a workflow run holds an open reserve.usedreflects credits consumed in the current billing period.plan_grantis the total monthly credit allowance for the caller's plan, enabling a "X / Y used" display.period_startandperiod_endmark the boundaries of the current billing window; free-tier callers use a calendar-month boundary.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.users.get_my_credits()
-
-
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.users.get_my_plan_limits() -> ApiResponsePlanLimits
-
-
-
Return the plan limits that govern the caller's current tier.
Includes numeric quotas (
monthly_credits,concurrent_runs_per_user,storage_bytes_per_workspace,workspaces_per_owner) and feature flags (byok_enabled,auto_fix_enabled,auto_edit_enabled).nullon list fields such astts_models_allowlistorsupported_languagesmeans all available options are permitted. Use this endpoint to gate feature access in your application rather than hardcoding tier names, which may change.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.users.get_my_plan_limits()
-
-
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.users.get_current_notification_preferences() -> ApiResponseEmailNotificationPreferencesOut
-
-
-
Return the caller's current email notification settings.
Each boolean field corresponds to a notification category.
truemeans the caller will receive that email;falsemeans they have opted out. UsePATCH /me/notification-preferencesto change individual preferences.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.users.get_current_notification_preferences()
-
-
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.users.update_current_notification_preferences(...) -> ApiResponseEmailNotificationPreferencesOut
-
-
-
Partially update the caller's email notification preferences.
Send only the fields you want to change; omitted fields are left unchanged. All provided fields must be boolean — explicit
nullvalues are rejected with a 422. Returns the full updated preference object.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.users.update_current_notification_preferences()
-
-
-
completed_generation_email:
typing.Optional[bool]— Set to true to enable or false to disable completion emails. Omit to leave unchanged.
-
failed_generation_email:
typing.Optional[bool]— Set to true to enable or false to disable failure emails. Omit to leave unchanged.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.users.list_my_templates(...) -> ApiListResponseTemplateOut
-
-
-
List workflow templates created by the caller in the current workspace.
Returns only templates owned by the caller; templates shared by other workspace members or platform starter templates are not included — use
GET /api/v1/templatesfor the full gallery. Supports offset-based pagination viaoffset/limit. Combinecategory,search, andfavorites_onlyto narrow results; multiplecategoryvalues are OR'd.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.users.list_my_templates()
-
-
-
category:
typing.Optional[typing.List[TemplateCategory]]— Repeat for OR, e.g. ?category=media&category=creative
-
search:
typing.Optional[str]— Full-text search against template name and description.
-
sort:
typing.Optional[ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort]— Sort order:recent(last updated),name(A–Z), oruses(most used).
-
offset:
typing.Optional[int]— Number of results to skip for pagination.
-
limit:
typing.Optional[int]— Maximum number of results to return (1–100).
-
favorites_only:
typing.Optional[bool]
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.list(...) -> ApiCountedListResponseWorkflowListItem
-
-
-
List workflows in the current workspace.
Returns a counted, paginated list of workflows scoped to the
X-Workspace-Idheader. Each item includes aggregate stats (runs_count,last_run_at,last_run_status) computed over all runs for that workflow.Status filter:
statusnarrows by the UI-derived state of the workflow's most recent run.completedmatches only workflows whose latest run succeeded (completed-only), andfailedmatches only workflows whose latest run failed — the two buckets are disjoint. A workflow whose latest run wascancelledmatches neither bucket and surfaces only in the unfiltered list.runningmatches active (running or paused) workflows.draftmatches workflows with no runs yet.pausedis accepted but currently returns no results.Multi-sort:
sortandorderare parallel query lists.?sort=runs_count&sort=name&order=desc&order=ascorders primarily byruns_count DESC, then byname ASC. Whenorderhas fewer entries thansort, missing positions use per-field defaults (name=asc,updated_at=desc,runs_count=desc). Omittingsortdefaults toupdated_at DESC. A stableid ASCtiebreaker is always appended so offset/limit pagination is consistent when sort keys tie.Date range:
last_run_after/last_run_beforefilter by the time of the most recent run. Both must be ISO 8601 with a UTC offset; a naive datetime returns 422. An inverted range (after > before) also returns 422.Failure history:
has_failed_runis orthogonal tostatus.statuskeys off the latest run only;has_failed_run=truematches workflows with afailedrun anywhere in their history, so a workflow whose latest run completed still matches if an earlier run failed. It composes with the other filters (AND).cancelledruns do not count as failures.pagination.totalreflects the filtered count for the current query.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.list()
-
-
-
status:
typing.Optional[WorkflowListStatus]— UI workflow status filter.completedmatches workflows whose latest run succeeded (completed-only);failedmatches failed-only — the two are disjoint. A workflow whose latest run was cancelled matches neither and appears only in the unfiltered list.pausedis accepted for forward compatibility and currently returns no rows.
-
search:
typing.Optional[str]— Case-insensitive search over name and description.
-
sort:
typing.Optional[typing.List[ListWorkflowsRequestSortItem]]— Repeat for multi-sort. Pairs withorderindex-wise.
-
order:
typing.Optional[typing.List[ListWorkflowsRequestOrderItem]]— Parallel to sort[]; shorter is padded with per-field defaults.
-
last_run_after:
typing.Optional[datetime.datetime]— Filter workflows whose last_run_at is at or after this ISO datetime (ISO 8601 with UTC offset required).
-
last_run_before:
typing.Optional[datetime.datetime]— Filter workflows whose last_run_at is at or before this ISO datetime (ISO 8601 with UTC offset required).
-
has_failed_run:
typing.Optional[bool]— Filter by failure history — ORTHOGONAL tostatus(which is latest-run based).truereturns only workflows with at least one run that ended infailedstate anywhere in their history; a workflow whose latest run succeeded still matches if an earlier run failed.falsereturns only workflows that have never had a failed run. Composes (ANDs) withstatus/search/date filters.cancelledruns are not treated as failures.
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Maximum items to return (1–100).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.create_workflow(...) -> ApiResponseWorkflowOut
-
-
-
Create a new workflow in the current workspace.
Validates the workflow
definition(graph structure, node types, edge connectivity) before persisting. Returns 422 with structured details if the definition fails validation. Requires at leasteditorrole in the workspace; viewers cannot create workflows.The
definitioncontains agraph(nodes and edges) and anexecutionblock (ordered step list and execution params). Omittingdefinitioncreates a workflow with an empty graph that can be edited later.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.create_workflow( name="name", )
-
-
-
name:
str— Human-readable workflow name (1–200 characters, non-blank).
-
workspace_id:
typing.Optional[str]
-
description:
typing.Optional[str]— Optional description shown in the workflow list (max 5000 characters).
-
definition:
typing.Optional[WorkflowDefinitionInput]— Graph and execution config. Omit to create an empty workflow.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.get(...) -> ApiResponseWorkflowOut
-
-
-
Fetch a single workflow by ID.
Returns the full workflow including its
definition(graph nodes/edges and execution config), aggregate run stats, and the latest run status. Thedefinitionis returned with any backwards-compatible config migrations applied, so node configs always reflect the current schema even if the workflow was saved with an older version.Use
GET /workflowsto list multiple workflows without fetching their full definitions.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.get( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.update_workflow(...) -> ApiResponseWorkflowOut
-
-
-
Replace a workflow's name, description, and definition (full update).
All fields in the request body are required. The
definitionis validated before persisting; an invalid graph returns 422. Existing runs are not affected — each run captures adefinition_snapshotat start time. Requires at leasteditorrole. UsePATCHto update only specific fields without supplying the full definition.
-
-
-
from onepin import OnePinClient, WorkflowDefinitionInput from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.update_workflow( workflow_id="workflow_id", name="name", definition=WorkflowDefinitionInput(), )
-
-
-
workflow_id:
str
-
name:
str— Human-readable workflow name (1–200 characters, non-blank).
-
definition:
WorkflowDefinitionInput— Full replacement graph and execution config. Must be valid.
-
workspace_id:
typing.Optional[str]
-
description:
typing.Optional[str]— Optional description (max 5000 characters). Pass null to clear.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.delete_workflow(...) -> ApiResponseDict
-
-
-
Delete a workflow and hide it from all list and get endpoints.
The workflow is soft-deleted: its data (including runs and their outputs) is retained for audit and GDPR-purge purposes but is no longer accessible via the API. Subsequent
GET,PUT,PATCH, or run requests on the same ID return 404. Requires at leasteditorrole.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.delete_workflow( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.patch_workflow(...) -> ApiResponseWorkflowOut
-
-
-
Partially update a workflow — only supplied fields are changed.
Any combination of
name,description, anddefinitionmay be included; omitted fields are left unchanged. At least one field must be present (empty body returns 422). Ifdefinitionis provided it is fully validated; an invalid graph returns 422. Requires at leasteditorrole.Use
PUTwhen replacing the full workflow definition in one operation.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.patch_workflow( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
name:
typing.Optional[str]— New workflow name (1–200 characters). Omit to leave unchanged.
-
description:
typing.Optional[str]— New description (max 5000 characters). Omit to leave unchanged; pass null to clear.
-
definition:
typing.Optional[WorkflowDefinitionInput]— Replacement graph and execution config. Omit to leave unchanged; must be valid if supplied.
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.list_workflow_uploads(...) -> ApiListResponseUploadOut
-
-
-
List confirmed uploads attached to a workflow.
Returns only uploads that have been confirmed (fully transferred and committed to the workflow). In-progress or abandoned uploads are excluded. Each item includes a short-lived download URL for the uploaded file.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.list_workflow_uploads( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Maximum items to return (1–100).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.estimate_workflow(...) -> ApiResponseEstimateResponse
-
-
-
Estimate the credit cost of running a workflow without creating a run.
Computes a breakdown of expected credits per node type based on the workflow's current definition. No run is created, no credits are charged, and no side effects occur. Equivalent to
POST /runs/preview; prefer that path in new integrations as it is co-located with the run lifecycle.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.estimate_workflow( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.preview_run(...) -> ApiResponseEstimateResponse
-
-
-
Dry-run credit estimate for a workflow — no run is created.
Returns a per-node-type credit breakdown based on the workflow's current definition. No run is enqueued, no credits are charged, and the workflow state is not modified. Use this before calling
POST /runsto confirm the expected cost. Equivalent toPOST /estimate.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.preview_run( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs_summary(...) -> ApiResponseRunsSummaryOut
-
-
-
Aggregate run statistics for a workflow over an optional date window.
Returns per-status counts (
completed,failed,cancelled,pending,running,paused) plus two derived metrics:pass_rate:completed / (completed + failed + cancelled).nullwhen there are no terminal runs in the window.average_duration_seconds: mean ofcompleted_at - started_atover successfully completed runs only.nullwhen no runs have completed.
Date range:
from/tofilter bycreated_at. Both must be ISO 8601 with a UTC offset; a naive datetime returns 422. An inverted range (from > to) also returns 422. Omit both to aggregate over all runs.Use
GET /runswith?status=filters for individual run details; this endpoint is best for dashboard-style health metrics.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs_summary( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
from:
typing.Optional[datetime.datetime]— Filter runs by created_at >= this ISO datetime (ISO 8601 with UTC offset required).
-
to:
typing.Optional[datetime.datetime]— Filter runs by created_at <= this ISO datetime (ISO 8601 with UTC offset required).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.get_run_steps(...) -> ApiResponseListWorkflowRunStepOut
-
-
-
List per-node execution steps for a workflow run.
Returns one entry per node execution attempt, ordered by execution sequence. Each step includes the node type, status, iteration number (for nodes that are retried), start/completion timestamps, and the node's
resultoutput.For audio output nodes,
resultis hydrated with short-livedplayback_urlvalues (valid for 15 minutes) so callers can stream audio directly without a separate download step.node_display_nameis resolved from the run's definition snapshot, so it reflects the name the node had when the run executed. Nodes that were retried appear as multiple steps with incrementingiterationvalues.For a higher-level view with aggregated metrics (pass rates, audio duration by language), use
GET /runs/{run_id}/overview. For paginated, grouped script+audio rows suitable for a data table, useGET /runs/{run_id}/data.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.get_run_steps( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.get_run_overview(...) -> ApiResponseWorkflowRunOverviewOut
-
-
-
Fetch server-computed overview aggregates for a workflow run.
Returns structured metric sections (e.g. audio duration totals, validation pass rates) grouped by display section, along with per-language audio breakdowns and per-validator scoring summaries. Also includes a
workflow_snapshotwith the graph definition and per-node completion states.This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows:
GET /runs/{run_id}— full run record including the raw definition snapshot.GET /runs/{run_id}/status— volatile status fields only; for polling.GET /runs/{run_id}/steps— flat per-node step log with audio playback URLs.GET /runs/{run_id}/data— paginated script+audio rows for a data table.GET /runs/{run_id}/overview(this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.get_run_overview( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.get_run_data(...) -> WorkflowRunDataResponse
-
-
-
Paginated script-and-audio data rows for a completed workflow run.
Returns grouped rows where each row represents one source script line. Within each row,
cardscontain the per-language audio outputs, per-card validation scores (word accuracy, naturalness), and short-lived audioplayback_urlvalues (valid for 15 minutes).Filtering:
searchnarrows which rows are returned based on their source script text.languagenarrows thecardslist within each returned row to a single locale. Rows with no matching cards are still returned (with emptycards), andpagination.totalalways reflects the search-filtered row count regardless oflanguage.
Pagination:
pagination.totalis scoped to thesearchfilter only.Response includes a
partialfield indicating whether any data is still being computed (e.g. audio not yet generated, validation not yet scored). This endpoint setsCache-Control: no-storebecause playback URLs are short-lived and data may change while a run is still in progress.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.get_run_data( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
search:
typing.Optional[str]— Case-insensitive search over the source/script text of each row.
-
language:
typing.Optional[str]— Exact full-locale code to filter cards within each row (e.g.en-US)._is normalized to-. Filtering is card-level only — rows remain visible even when all their cards are filtered out, andpagination.totalis unaffected.
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Maximum rows to return (1–100).
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.download_run(...) -> ApiResponseDownloadUrlOut
-
-
-
Create a temporary download URL for a complete workflow run export.
Returns a pre-signed URL pointing to a ZIP archive containing all audio output files produced by the run. The URL is valid for 15 minutes (
expires_at). The archive is generated on first request and cached for subsequent calls; re-calling this endpoint before expiry returns a new URL for the same cached archive.Only available for runs in
completedstatus — returns 409 for runs that are still active or ended infailed/cancelled. Returns 404 if the run produced no audio files.To download output from a single output node rather than the whole run, use
GET /runs/{run_id}/nodes/{node_id}/download.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.download_run( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.download_run_node(...) -> ApiResponseDownloadUrlOut
-
-
-
Create a temporary download URL for a single output node's audio export.
Returns a pre-signed URL for a ZIP archive containing the audio files produced by one specific output node within the run. Useful when a workflow has multiple output nodes and the caller wants only one node's results rather than the full run archive.
node_idmust identify an output-category node in the run's definition snapshot. Passing a node ID that belongs to a non-output node type (e.g. a processing or validation node) returns 404. Returns 404 if the node produced no audio files, and 409 if the run has not yet completed.The URL is valid for 15 minutes. To download all output nodes in a single archive, use
GET /runs/{run_id}/downloadinstead.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.download_run_node( workflow_id="workflow_id", run_id="run_id", node_id="node_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
node_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.pause_run(...) -> ApiResponseWorkflowRunOut
-
-
-
Pause an active workflow run at the next safe checkpoint.
For a running run, the current wave of parallel nodes is allowed to finish before the run parks (in-flight work is preserved, not abandoned). For a pending run that has not yet started, it parks immediately. The run transitions to
pausedstatus once drained; during the drain period,statusremainsrunningwithpause_requested_atset.The operation is idempotent: pausing an already-paused run returns it unchanged. A paused run can be resumed via
POST /runs/{run_id}/resumeor permanently stopped viaPOST /runs/{run_id}/cancel.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.pause_run( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.resume_run(...) -> ApiResponseWorkflowRunOut
-
-
-
Resume a paused workflow run from its last completed wave.
Transitions the run from
pausedback torunningand schedules execution to continue from where it left off — no nodes that already completed are re-executed.Returns 409 if the workspace already has another active run for this workflow, or if the caller is at the concurrent-run limit. In that case the run stays
pausedand the caller can retry later. Only runs inpausedstatus can be resumed; attempting to resume arunning,completed,failed, orcancelledrun returns 409.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.resume_run( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.duplicate_workflow(...) -> ApiResponseWorkflowOut
-
-
-
Create a copy of an existing workflow in the same workspace.
The new workflow inherits the source's
name(suffixed with " (Copy)"),description, anddefinition. Runs from the original workflow are not copied — the duplicate starts with zero runs. Requires at leasteditorrole. Returns 201 with the new workflow on success.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.duplicate_workflow( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs.list(...) -> ApiCountedListResponseWorkflowRunListItem
-
-
-
List runs for a workflow, newest first by default.
Returns a counted, paginated list of runs for the specified workflow. Each item includes the run's status, step progress (
total_steps,finished_steps), credit usage, and the actor who triggered it.Status filter: Pass
?status=completed,failedto OR-match multiple statuses. Values must be the raw lowercase RunStatus strings. Unknown values or empty tokens (e.g.a,,b) return 422.Pagination:
pagination.totalreflects the filtered count. Sort tiebreaks always appendid ASCfor stable offset/limit pagination.For aggregate statistics (pass rate, average duration) across all runs, use
GET /runs/summaryinstead.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs.list( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
offset:
typing.Optional[int]— Zero-based pagination offset.
-
limit:
typing.Optional[int]— Maximum items to return (1–100).
-
status:
typing.Optional[str]— Comma-separated raw RunStatus values (e.g.completed,failed). Values are case-sensitive lowercase:pending,running,completed,failed,cancelled,paused. Multiple values OR-match. Empty tokens (e.g.a,,b) and unknown values return 422.
-
search:
typing.Optional[str]— Case-insensitive search over the triggering user's display name (falls back to email).
-
sort:
typing.Optional[ListRunsRequestSort]— Sort field:created_at|started_at|completed_at|status. Defaults tocreated_at.
-
order:
typing.Optional[ListRunsRequestOrder]—ascordesc. Defaults todesc.
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs.start(...) -> ApiResponseWorkflowRunOut
-
-
-
Start a new execution of a workflow (202 Accepted).
Enqueues the workflow for asynchronous execution and returns the newly created run in
pendingorrunningstatus. The run progresses through its nodes in the background; pollGET /runs/{run_id}/statusfor lightweight progress updates, orGET /runs/{run_id}once to load the immutable definition snapshot.Use
POST /runs/previeworPOST /estimateto compute the credit cost before committing to an actual run — those endpoints are read-only and incur no charges.Returns 409 if the workspace is at its concurrent-run limit or another run for this workflow is already active.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs.start( workflow_id="workflow_id", )
-
-
-
workflow_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs.get(...) -> ApiResponseWorkflowRunDetailOut
-
-
-
Fetch full detail for a single workflow run.
Returns all run fields plus
definition_snapshot— the graph and execution config captured at the moment the run started. The snapshot is returned raw (no config migrations applied), so it faithfully represents the workflow as it existed for this specific execution even if the workflow definition has since been edited.This is the heaviest run endpoint. For progress polling, use the lighter
GET /runs/{run_id}/statuswhich omits the snapshot. For aggregated visual metrics, useGET /runs/{run_id}/overview. For the per-node step log with audio playback URLs, useGET /runs/{run_id}/steps.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs.get( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs.status(...) -> ApiResponseWorkflowRunStatusOut
-
-
-
Lightweight run status for progress polling.
Returns only the volatile, frequently-changing fields:
status, step counts (total_steps,finished_steps), timestamps (started_at,completed_at,paused_at,pause_requested_at),usage_summary,error, andhas_export. The definition snapshot is intentionally omitted to keep response size small.Recommended polling pattern: call
GET /runs/{run_id}once after starting a run to load the immutable definition snapshot and initial metadata, then poll this endpoint untilstatusreaches a terminal value (completed,failed, orcancelled).has_exportbecomingtruesignals that a download is ready viaGET /runs/{run_id}/download.The transient
pausingstate is observable here:status == "running"withpause_requested_atset means a pause is in progress but the current wave has not yet finished draining.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs.status( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-
client.workflows.runs.cancel(...) -> ApiResponseWorkflowRunOut
-
-
-
Cancel an active workflow run.
Immediately marks the run as
cancelledand stops any further processing. In-flight work at the current node may be abandoned mid-execution. The operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error.Only runs in
pending,running, orpausedstatus can be cancelled. Runs that have already reached a terminal state (completed,failed,cancelled) return 409.Unlike
pause, cancel is permanent — a cancelled run cannot be resumed. Usepauseif you intend to continue the run later.
-
-
-
from onepin import OnePinClient from onepin.environment import OnePinClientEnvironment client = OnePinClient( token="<token>", environment=OnePinClientEnvironment.PROD, ) client.workflows.runs.cancel( workflow_id="workflow_id", run_id="run_id", )
-
-
-
workflow_id:
str
-
run_id:
str
-
workspace_id:
typing.Optional[str]
-
request_options:
typing.Optional[RequestOptions]— Request-specific configuration.
-
-