All Turnkey mutation endpoints are asynchronous — when you call a mutation, the API immediately returns an activity object. Your code must poll until that activity reaches a terminal state. The exceptions are the private key signing endpoints (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tkhq/sdk/llms.txt
Use this file to discover all available pages before exploring further.
signTransaction, signRawPayload, signRawPayloads), which are synchronous and return results directly.
Activity statuses
Every activity has astatus field that progresses through the following states:
| Status | Meaning |
|---|---|
ACTIVITY_STATUS_CREATED | Activity was received and is being processed |
ACTIVITY_STATUS_PENDING | Activity is pending consensus or awaiting a quorum response |
ACTIVITY_STATUS_CONSENSUS_NEEDED | Activity requires additional approvals before it can proceed |
ACTIVITY_STATUS_COMPLETED | Activity finished successfully — results are available |
ACTIVITY_STATUS_FAILED | Activity failed; check the error details |
ACTIVITY_STATUS_REJECTED | Activity was rejected by a policy or consensus vote |
COMPLETED, FAILED, REJECTED) are exported as the TERMINAL_ACTIVITY_STATUSES constant from @turnkey/http.
createActivityPoller
createActivityPoller is the recommended way to poll activities when using TurnkeyClient. It wraps any client mutation method, submits the request, then polls until the activity reaches a terminal status.
The
TurnkeyClient instance used for polling.The client method to call. Must be a method that returns an activity response — for example,
client.createPrivateKeys.How often to poll, in milliseconds. Defaults to
500.withAsyncPolling
withAsyncPolling is an older helper that wraps the lower-level TurnkeyApi static fetchers (not the TurnkeyClient instance methods). It is still functional but is considered deprecated in favor of createActivityPoller.
TurnkeyActivityError
When an activity reachesACTIVITY_STATUS_FAILED, ACTIVITY_STATUS_REJECTED, or ACTIVITY_STATUS_CONSENSUS_NEEDED, the poller throws a TurnkeyActivityError:
TurnkeyActivityConsensusNeededError subclass that is thrown specifically when status is ACTIVITY_STATUS_CONSENSUS_NEEDED. It has the same properties.
Handling consensus
Some organizations require multi-party approval (consensus) before certain activities can complete. When this happens:- The poller throws
TurnkeyActivityErrorwithactivityStatus === "ACTIVITY_STATUS_CONSENSUS_NEEDED". - Store the
activityIdfrom the error for later retrieval. - Once approvals are collected out-of-band, call
client.getActivity({ activityId, organizationId })to re-fetch the final status. - Use the helper functions to extract results from the completed activity:
Best practices
- Always catch
TurnkeyActivityErrorwhen using a poller. Network errors or API errors will surface as plainErrororTurnkeyRequestErrorinstances. - Keep
refreshIntervalMsat the default500msfor most use cases. Decrease it only if your application is latency-sensitive and you are willing to pay for the extra requests. - For consensus-gated activities, do not rely on the poller to eventually return — it will throw immediately when consensus is needed. Design your flow to handle this case explicitly.
- Use
TERMINAL_ACTIVITY_STATUSESto check whether a status you have retrieved is final before deciding whether to poll again.