All requests require an API key via the
X-API-Key header. This endpoint requires a secret key (sk_live_) even though it is a read, because the response contains a signed payload. Call it from your backend.
See Authentication for details.Overview
GET /v2/streams/{id}/admin-operations/active returns the admin operation currently blocking a token-based stream, and until when it blocks it.
An admin operation is a backend-signed change to a stream’s funds that the stream admin submits to the StreamFactory. There are two kinds today:
- a withdrawal, signed by Withdraw Funds
- a budget increase, made outside the Earn API
- Recover a lost payload. If your client lost the
txParamsof a signed operation (a closed browser, a dismissed wallet prompt), the endpoint returns the same payload. Nothing is re-signed, so it grants nothing the original signature did not. - Check whether the operation executed. Once
confirmedTxHashis set, the transaction landed on-chain and must not be submitted again. - Know when the stream frees up.
blockingUntilis when the stream accepts a new withdrawal or budget increase.
Endpoint
Parameters
Path Parametersuuid
required
Stream identifier, as returned in
id by Get Streams. The stream must be token-based and belong to the organization attached to the API key.Response Examples
Response Fields
ActiveAdminOperation | null
required
The admin operation blocking the stream.
null when the stream accepts a new withdrawal or budget increase.ActiveAdminOperation
string
required
Which
StreamFactory function txParams calls, and therefore the shape of txParams.params.params: withdraw (withdrawFunds) or add_funds (addFunds).object
required
Signed payload of the operation, exactly as it was issued.
integer
required
Chain where the stream lives and where the transaction must be submitted.
string
required
Stream admin wallet. It is the only wallet that can submit the transaction.
object
required
Signed arguments of the
StreamFactory call. Exactly one of two shapes, selected by type:withdraw:stream,to, andamount, all presentadd_funds:stream,netAmount, andfeeAmount, all present
withdraw payload carries no netAmount or feeAmount, and an add_funds payload carries no to or amount.string
required
Stream contract address. Present for both types.
string
withdraw only. Recipient of the withdrawn tokens.string
withdraw only. Amount to withdraw in the reward token’s smallest unit.string
add_funds only. Budget increase in the reward token’s smallest unit.string
add_funds only. Fee charged on top of netAmount, in the reward token’s smallest unit.string
required
Unique 32-byte value (hex) that makes the signature single-use.
integer
required
Unix timestamp, in seconds, after which the signature is no longer accepted on-chain. Returned as a JSON number.
string
required
EIP-712 signature bytes serialized as base64 in JSON.
datetime
required
When the stream accepts a new withdrawal or budget increase again. See When the stream frees up.
datetime | null
required
Block time of the transaction that executed the operation.
null until it executes.string | null
required
Hash of the transaction that executed the operation.
null until it executes. Once set, do not submit txParams again.Operation Lifecycle
When the stream frees up
blockingUntil is the earlier of:
txParams.params.deadlineplus a one-minute tolerance for chain clock skew. After that, the signature can no longer be used.confirmedAtplus the finality window of the stream’s chain. After that, the executed transaction can no longer be reverted by a reorg.
For example, an Ethereum operation signed with a one-hour expiration and executed 20 minutes later frees the stream 15 minutes after execution, well before its deadline.
Resume a Pending Operation
Read the operation from your backend, then let the stream admin wallet submit it according totype. The StreamFactory address for each chain is listed in StreamFactory addresses by chain.
Operational Notes
Nothing is re-signed
Nothing is re-signed
The endpoint returns the payload that was signed when the operation was created: same parameters, same
salt, same deadline. Calling it repeatedly never extends the deadline or creates a new signature.Budget increases also block withdrawals
Budget increases also block withdrawals
A budget increase made outside the Earn API blocks the stream exactly like a withdrawal does. It shows up here with
type: "add_funds", and Withdraw Funds rejects new requests until its blockingUntil.Confirmation is detected on-chain
Confirmation is detected on-chain
confirmedAt and confirmedTxHash are set when Turtle detects the executing transaction on-chain. They can lag a few moments behind the transaction receipt your wallet returns.Point-based streams have no admin operations
Point-based streams have no admin operations
Point-based streams hold no on-chain funds, so they cannot be withdrawn from or topped up through the
StreamFactory. Requesting one returns 400 Bad Request.A valid API key alone is not enough
A valid API key alone is not enough
This endpoint requires three things at the same time: a valid
X-API-Key header, a secret key, and the organization:incentivize:streams permission on the organization attached to that key.Error Handling
Missing or invalid API key
Missing or invalid API key
Status Code: 401 UnauthorizedA key that is present but invalid, inactive, or expired returns
401 as well, with "Invalid API key", "API key is inactive", or "API key has expired".Solution: Pass a valid X-API-Key header.Publishable key used
Publishable key used
Status Code: 403 ForbiddenSolution: Call this endpoint from your backend with a secret key (
sk_live_).Permission denied
Permission denied
Status Code: 403 ForbiddenSolution: Use an API key associated with an organization that has the
organization:incentivize:streams permission.Point-based stream
Point-based stream
Status Code: 400 Bad RequestSolution: Only request token-based streams.
Stream not found
Stream not found
Status Code: 404 Not FoundThis happens when the
id path parameter does not correspond to a stream owned by the organization attached to the API key.Rate limit exceeded
Rate limit exceeded
Status Code: 429 Too Many RequestsUsage is metered per key, hourly and monthly. Every response carries the hourly budget in the
X-RateLimit-* headers; keys with a monthly limit also get X-Monthly-* headers. A monthly overrun returns "Monthly usage limit exceeded" instead.Solution: Back off until the window resets — hourly limits also return Retry-After — or ask the Turtle team for a higher limit. See Rate limits.Unexpected internal error
Unexpected internal error
Status Code: 500 Internal Server ErrorSolution: Retry the request and contact Turtle if the issue persists.

