Skip to main content

Funding Transaction Streaming

Subscribe to real-time funding transaction state changes (deposits, withdrawals) using gRPC streaming. This is the recommended approach for monitoring funding status.
Rate Limiting NoticeThe REST endpoint GET /v1/funding/transactions is rate limited. For real-time funding status updates, prefer the gRPC streaming connection to avoid rate limit issues and reduce latency.

Service Definition

Service: polymarket.v1.FundingAPI RPC: CreateFundingTransactionSubscription Type: Server-side streaming
service FundingAPI {
    rpc CreateFundingTransactionSubscription(CreateFundingTransactionSubscriptionRequest)
        returns (stream CreateFundingTransactionSubscriptionResponse);
}

Request Parameters

CreateFundingTransactionSubscriptionRequest

FieldTypeRequiredDescription
account_idslist[str]NoFilter by funding account IDs. Empty = all authorized accounts.
transaction_typeslist[FundingTransactionType]NoFilter by transaction type. Empty = all types.
resume_timeTimestampNoResume from a previous position for reconnection.

Example Request

from polymarket.v1 import funding_pb2

# Subscribe to all funding transactions for your accounts
request = funding_pb2.CreateFundingTransactionSubscriptionRequest(
    account_ids=[],
    transaction_types=[]
)

# Subscribe to deposits only
request = funding_pb2.CreateFundingTransactionSubscriptionRequest(
    account_ids=[],
    transaction_types=[funding_pb2.TRANSACTION_TYPE_DEPOSIT]
)

# Subscribe to specific account
request = funding_pb2.CreateFundingTransactionSubscriptionRequest(
    account_ids=["your-account-id"],
    transaction_types=[]
)

Response Messages

The stream returns CreateFundingTransactionSubscriptionResponse messages when transaction states change.

Response Fields

FieldTypeDescription
changeslist[FundingTransactionChange]Transaction state changes in this batch
server_timeTimestampServer timestamp (store for resume_time on reconnection)

FundingTransactionChange

FieldTypeDescription
transactionFundingTransactionThe updated transaction with current state
previous_stateFundingTransactionStateThe state before this change
change_timeTimestampWhen this change was detected

Transaction States

StateValueDescription
TRANSACTION_STATE_PENDING0Transaction initiated, awaiting processing
TRANSACTION_STATE_PROCESSING9Transaction being processed
TRANSACTION_STATE_ACKNOWLEDGED1Transaction acknowledged by payment provider
TRANSACTION_STATE_COMPLETED2Transaction successfully completed
TRANSACTION_STATE_CANCELLED3Transaction cancelled
TRANSACTION_STATE_ALLOCATED4Funds allocated
TRANSACTION_STATE_REFUNDED6Transaction fully refunded
TRANSACTION_STATE_PARTIALLY_REFUNDED5Transaction partially refunded
TRANSACTION_STATE_RELEASED8Funds released
TRANSACTION_STATE_PARTIALLY_RELEASED7Funds partially released

Common State Transitions

Deposit Flow:
PENDING → PROCESSING → ACKNOWLEDGED → COMPLETED

Deposit Failure:
PENDING → PROCESSING → CANCELLED

Withdrawal Flow:
PENDING → PROCESSING → COMPLETED

Refund Flow:
COMPLETED → PARTIALLY_REFUNDED → REFUNDED

Transaction Types

TypeValueDescription
TRANSACTION_TYPE_DEPOSIT1Deposit into account
TRANSACTION_TYPE_WITHDRAWAL2Withdrawal from account
TRANSACTION_TYPE_TRANSFER3Internal transfer
TRANSACTION_TYPE_MANUAL_ADJUSTMENT4Manual adjustment
TRANSACTION_TYPE_SETTLEMENT_FEE5Settlement fee
TRANSACTION_TYPE_EXECUTION_FEE7Trading execution fee

Complete Example

import grpc
from datetime import datetime
from polymarket.v1 import funding_pb2
from polymarket.v1 import funding_pb2_grpc


class FundingTransactionStreamer:
    def __init__(self, grpc_server: str = "grpc-api.preprod.polymarketexchange.com:443"):
        self.grpc_server = grpc_server
        self.access_token = None
        self.last_server_time = None  # For resume capability

    def stream_funding_transactions(self, account_ids: list = None,
                                     transaction_types: list = None,
                                     resume_time=None):
        """Stream funding transaction state changes."""
        if not self.access_token:
            raise ValueError("Not authenticated. Please login first.")

        # Create credentials and channel
        credentials = grpc.ssl_channel_credentials()
        channel = grpc.secure_channel(self.grpc_server, credentials)
        stub = funding_pb2_grpc.FundingAPIStub(channel)

        # Create request
        request = funding_pb2.CreateFundingTransactionSubscriptionRequest(
            account_ids=account_ids or [],
            transaction_types=transaction_types or []
        )

        # Add resume_time if reconnecting
        if resume_time:
            request.resume_time.CopyFrom(resume_time)

        # Set up metadata with authorization
        metadata = [('authorization', f'Bearer {self.access_token}')]

        try:
            print("Starting funding transaction stream...")
            print(f"Account filters: {account_ids or 'ALL'}")
            print(f"Type filters: {transaction_types or 'ALL'}")
            print("-" * 60)

            response_stream = stub.CreateFundingTransactionSubscription(
                request, metadata=metadata
            )

            for response in response_stream:
                self._process_response(response)

        except grpc.RpcError as e:
            print(f"gRPC error: {e.code()} - {e.details()}")
            raise
        except KeyboardInterrupt:
            print("\nStream interrupted by user")
        finally:
            channel.close()

    def _process_response(self, response):
        """Process funding transaction change response."""
        # Store server_time for resume capability
        if response.HasField('server_time'):
            self.last_server_time = response.server_time

        for change in response.changes:
            tx = change.transaction
            print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Transaction State Change")
            print(f"  Transaction ID: {tx.transaction_id}")
            print(f"  Type: {funding_pb2.FundingTransactionType.Name(tx.transaction_type)}")
            print(f"  Amount: {tx.amount} {tx.currency}")
            print(f"  Previous State: {funding_pb2.FundingTransactionState.Name(change.previous_state)}")
            print(f"  Current State: {funding_pb2.FundingTransactionState.Name(tx.transaction_state)}")
            print(f"  Account ID: {tx.account_id}")

            if tx.after_balance:
                print(f"  New Balance: {tx.after_balance}")

            print("-" * 60)


# Usage
if __name__ == "__main__":
    streamer = FundingTransactionStreamer()

    # Authenticate first (see Authentication docs)
    # streamer.access_token = "your_access_token"

    # Stream all funding transactions
    streamer.stream_funding_transactions()

    # Or filter by type
    streamer.stream_funding_transactions(
        transaction_types=[funding_pb2.TRANSACTION_TYPE_DEPOSIT]
    )

Sample Output

Starting funding transaction stream...
Account filters: ALL
Type filters: ALL
------------------------------------------------------------

[14:30:15] Transaction State Change
  Transaction ID: tx_abc123
  Type: TRANSACTION_TYPE_DEPOSIT
  Amount: 100.00 USD
  Previous State: TRANSACTION_STATE_PENDING
  Current State: TRANSACTION_STATE_PROCESSING
  Account ID: acct_xyz789
------------------------------------------------------------

[14:30:45] Transaction State Change
  Transaction ID: tx_abc123
  Type: TRANSACTION_TYPE_DEPOSIT
  Amount: 100.00 USD
  Previous State: TRANSACTION_STATE_PROCESSING
  Current State: TRANSACTION_STATE_COMPLETED
  Account ID: acct_xyz789
  New Balance: 250.00
------------------------------------------------------------

Reconnection Handling

Store the server_time from each response to enable seamless reconnection:
# On disconnect, reconnect with resume_time
if streamer.last_server_time:
    streamer.stream_funding_transactions(
        resume_time=streamer.last_server_time
    )
The server polls for transaction changes every 15 seconds. State changes are broadcast to subscribers as they are detected.

Comparing REST vs Streaming

AspectREST (/v1/funding/transactions)gRPC Streaming
Rate LimitingYes - subject to rate limitsNo - single connection
LatencyPoll-based, higher latencyReal-time push (~15s detection)
EfficiencyMultiple requests neededSingle persistent connection
Use CaseOne-time queries, historical dataReal-time monitoring
Recommendation: Use the gRPC streaming endpoint for monitoring deposit/withdrawal status. Reserve the REST endpoint for one-time queries or fetching historical transaction data.

Next Steps