Tinybird SDK for PHP
PHP SDK for the Tinybird API — the real-time data platform for developers. Build low-latency, high-concurrency analytics APIs over any data source in minutes. Ingest millions of events per second, query with SQL, and publish endpoints instantly.
// Ingest → Query → Results
$tinybird = Client::create('p.your_token');
$tinybird->events()->send('clicks', ['user' => 'alice', 'page' => '/home']);
$result = $tinybird->query()->sql('SELECT count() FROM clicks');
// → {"data":[{"count()":1}],"rows":1}- High-frequency ingestion — Send millions of events per second via Events API
- Schema generation — Analyze files to generate Data Source schemas
- Sub-second queries — Execute SQL queries with instant results
- Concurrent requests — Batch multiple queries for parallel execution
- Multi-region support — EU, US, AWS, GCP, and custom deployments
- Built-in retry logic — Automatic retry with exponential backoff
- PSR-18 compatible — Works with Symfony, Guzzle, or any HTTP client
- Type-safe resources — Full PHP 8.1+ support with strict types
Install this package using Composer:
composer require brd6/tinybird-sdk-phpThis package uses PSR-18 HTTP client abstraction. You can use any compatible HTTP client. For quick setup with Symfony HTTP client:
composer require brd6/tinybird-sdk-php symfony/http-client nyholm/psr7use Brd6\TinybirdSdk\Client;
// Create client (uses EU region by default)
$tinybird = Client::create('p.your_token_here');
// Ingest events
$tinybird->events()->send('events', [
['timestamp' => '2025-01-01 00:00:00', 'event' => 'page_view', 'user_id' => 'user_123'],
['timestamp' => '2025-01-01 00:00:01', 'event' => 'click', 'user_id' => 'user_456'],
]);
// Query with SQL
$result = $tinybird->query()->sql('SELECT count() FROM events');
// Call a Pipe endpoint
$result = $tinybird->pipes()->query('analytics_endpoint', ['date_from' => '2025-01-01']);use Brd6\TinybirdSdk\Client;
use Brd6\TinybirdSdk\Enum\Region;
// US East
$tinybird = Client::forRegion('p.your_token', Region::GCP_US_EAST4);
// AWS EU Central
$tinybird = Client::forRegion('p.your_token', Region::AWS_EU_CENTRAL_1);
// Tinybird Local
$tinybird = Client::local('your_local_token');
// Custom port
$tinybird = Client::local('your_local_token', 8080);For private deployments or custom domains:
use Brd6\TinybirdSdk\Client;
use Brd6\TinybirdSdk\ClientOptions;
$options = (new ClientOptions())
->setToken('your_token')
->setBaseUrl('https://your-custom-endpoint.com');
$tinybird = new Client($options);Analyze files to generate Tinybird Data Source schemas. Useful before creating .datasource files.
// Analyze NDJSON records
$result = $tinybird->analyze()->analyzeRecords([
['timestamp' => '2025-01-01 00:00:00', 'event' => 'page_view', 'user_id' => 'user_123'],
['timestamp' => '2025-01-01 00:00:01', 'event' => 'click', 'user_id' => 'user_456'],
]);
// Get the generated schema (ready for .datasource files)
echo $result->getSchema();
// Output: timestamp DateTime `json:$.timestamp`, event String `json:$.event`, ...
// Inspect analyzed columns
foreach ($result->columns as $col) {
echo "{$col->name}: {$col->recommendedType}";
if ($col->presentPct < 1) {
echo " (nullable)";
}
}
// Analyze a remote file
$result = $tinybird->analyze()->analyzeUrl('https://example.com/data.ndjson');
// Analyze raw content
$result = $tinybird->analyze()->analyzeContent($csvContent);High-frequency data ingestion optimized for real-time analytics. This is the recommended way to ingest data in Tinybird Forward workspaces.
// Send single event
$result = $tinybird->events()->send('events', [
'timestamp' => '2025-01-01 00:00:00',
'event' => 'page_view',
'user_id' => 'user_123',
]);
// Send batch events
$result = $tinybird->events()->send('events', [
['timestamp' => '2025-01-01 00:00:00', 'event' => 'page_view', 'user_id' => 'user_123'],
['timestamp' => '2025-01-01 00:00:01', 'event' => 'click', 'user_id' => 'user_456'],
]);
// Check result
echo $result->successfulRows; // Rows ingested
echo $result->quarantinedRows; // Rows failed validation
// Send raw NDJSON
$tinybird->events()->sendRaw('events', $ndjsonString);Read Data Source information and metadata.
// List all Data Sources
$datasources = $tinybird->dataSources()->list();
foreach ($datasources as $ds) {
echo $ds->name;
echo $ds->getRowCount();
echo $ds->getBytes();
}
// Get Data Source details
$info = $tinybird->dataSources()->retrieve('events');
echo $info->id;
echo $info->name;
echo $info->type;
echo $info->createdAt;
// Access columns
foreach ($info->columns as $column) {
echo $column->name;
echo $column->type;
}
// Get quarantine data
$quarantine = $tinybird->dataSources()->quarantine('events');Note: For schema changes, use the Tinybird CLI (
tb deploy). See Tinybird Forward documentation.
Execute raw SQL queries against your Data Sources.
// Simple query
$result = $tinybird->query()->sql('SELECT count() FROM events');
echo $result->rows;
echo $result->data[0]['count()'];
// Query with parameters
$result = $tinybird->query()->sql(
'SELECT * FROM events WHERE user_id = {user_id:String} LIMIT {limit:Int32}',
['user_id' => 'user_123', 'limit' => 100]
);
// Access results
foreach ($result->data as $row) {
echo $row['event'];
}
// Query statistics
echo $result->getElapsedTime();
echo $result->getRowsRead();
echo $result->getBytesRead();Execute multiple SQL queries concurrently for better performance:
// Run multiple queries in parallel
$results = $tinybird->query()->batchSql([
'total_users' => 'SELECT count() FROM users',
'active_today' => 'SELECT count() FROM events WHERE date = today()',
'revenue' => 'SELECT sum(amount) FROM orders',
]);
// Access individual results
foreach ($results as $key => $result) {
if ($result->isSuccess()) {
echo "{$key}: " . $result->getData()->data[0];
} else {
echo "{$key} failed: " . $result->getException()->getMessage();
}
}
// Or get data directly
$totalUsers = $results['total_users']->getData()->data[0]['count()'];Query published API Endpoints and list Pipes.
// List Pipes
$pipes = $tinybird->pipes()->list();
// Query a Pipe endpoint
$result = $tinybird->pipes()->query('my_analytics_endpoint', [
'start_date' => '2025-01-01',
'end_date' => '2025-12-31',
'limit' => 1000,
]);
foreach ($result->data as $row) {
// Process results
}Query multiple Pipe endpoints concurrently:
// Simple: key is pipe name
$results = $tinybird->pipes()->batchQuery([
'user_stats' => ['date' => '2025-01-01'],
'event_counts' => ['type' => 'click'],
]);
// Query same pipe multiple times using # alias
$results = $tinybird->pipes()->batchQuery([
'user_stats#jan' => ['date' => '2025-01-01'],
'user_stats#feb' => ['date' => '2025-02-01'],
'user_stats#mar' => ['date' => '2025-03-01'],
]);
// Handle results with error isolation
foreach ($results as $key => $result) {
if ($result->isSuccess()) {
$data = $result->getData();
echo "{$key}: {$data->rows} rows";
} else {
// Individual failures don't affect other queries
echo "{$key} failed: " . $result->getException()->getMessage();
}
}Monitor and manage background jobs (imports, populates, copies).
use Brd6\TinybirdSdk\RequestParameters\ListJobsParams;
use Brd6\TinybirdSdk\Enum\JobStatus;
// List recent jobs
$jobs = $tinybird->jobs()->list();
// Filter by status
$jobs = $tinybird->jobs()->list(new ListJobsParams(status: JobStatus::DONE));
// Get job details
$job = $tinybird->jobs()->retrieve($jobId);
echo $job->status; // waiting, working, done, error
// Cancel a running job
$tinybird->jobs()->cancel($jobId);Manage workspace variables for use in Pipes.
// List all variables
$vars = $tinybird->variables()->list();
// Create a variable
$var = $tinybird->variables()->create('API_KEY', 'secret_value');
// Update a variable
$tinybird->variables()->update('API_KEY', 'new_value');
// Delete a variable
$tinybird->variables()->remove('API_KEY');Manage workspace tokens for authentication.
use Brd6\TinybirdSdk\RequestParameters\CreateTokenParams;
// List all tokens
$tokens = $tinybird->tokens()->list();
// Create a token with scopes
$token = $tinybird->tokens()->create(new CreateTokenParams(
name: 'my_token',
scopes: ['PIPES:READ', 'DATASOURCES:READ'],
));
// Refresh (rotate) a token
$newToken = $tinybird->tokens()->refresh('my_token');
// Delete a token
$tinybird->tokens()->remove('my_token');Export data to object stores (S3, GCS).
use Brd6\TinybirdSdk\RequestParameters\CreateSinkParams;
// Create a sink pipe
$pipe = $tinybird->sinkPipes()->create($pipeId, $nodeId, new CreateSinkParams(
connection: 's3://bucket/path',
path: 'exports/',
));
// Trigger a sink export
$result = $tinybird->sinkPipes()->trigger($pipeId);
// Get S3 integration settings
$settings = $tinybird->sinkPipes()->getS3Settings();use Brd6\TinybirdSdk\Exception\ApiException;
use Brd6\TinybirdSdk\Exception\AuthenticationException;
use Brd6\TinybirdSdk\Exception\RateLimitException;
use Brd6\TinybirdSdk\Exception\RequestTimeoutException;
try {
$result = $tinybird->pipes()->query('my_endpoint');
} catch (AuthenticationException $e) {
// Invalid or expired token (401/403)
// Includes helpful suggestions for region mismatches
} catch (RateLimitException $e) {
// Too many requests (429)
$retryAfter = $e->getRetryAfter();
$limit = $e->getRateLimitLimit();
$remaining = $e->getRateLimitRemaining();
} catch (RequestTimeoutException $e) {
// Request timed out
} catch (ApiException $e) {
// Other API errors
$code = $e->getCode();
$message = $e->getMessage();
$response = $e->getResponse();
}| Region | Enum | API Base URL |
|---|---|---|
| GCP Europe West 3 (default) | Region::GCP_EUROPE_WEST3 |
https://api.tinybird.co |
| GCP Europe West 2 | Region::GCP_EUROPE_WEST2 |
https://api.europe-west2.gcp.tinybird.co |
| GCP US East 4 | Region::GCP_US_EAST4 |
https://api.us-east.tinybird.co |
| GCP North America | Region::GCP_NORTHAMERICA_NORTHEAST2 |
https://api.northamerica-northeast2.gcp.tinybird.co |
| AWS EU Central 1 | Region::AWS_EU_CENTRAL_1 |
https://api.eu-central-1.aws.tinybird.co |
| AWS EU West 1 | Region::AWS_EU_WEST_1 |
https://api.eu-west-1.aws.tinybird.co |
| AWS US East 1 | Region::AWS_US_EAST_1 |
https://api.us-east.aws.tinybird.co |
| AWS US West 2 | Region::AWS_US_WEST_2 |
https://api.us-west-2.aws.tinybird.co |
| Local | Region::LOCAL |
http://localhost:7181 |
use Brd6\TinybirdSdk\Client;
use Brd6\TinybirdSdk\ClientOptions;
use Brd6\TinybirdSdk\Enum\Region;
$options = (new ClientOptions())
->setToken(getenv('TINYBIRD_TOKEN'))
->setRegion(Region::AWS_EU_CENTRAL_1)
->setTimeout(120)
->setCompression(true)
->setRetryMaxRetries(5)
->setRetryDelayMs(1000)
->setRetryBackoffMultiplier(3);
$tinybird = new Client($options);| Option | Default | Description |
|---|---|---|
token |
'' |
Tinybird API token |
region |
Region::GCP_EUROPE_WEST3 |
API region |
baseUrl |
https://api.tinybird.co |
Custom API endpoint |
timeout |
60 |
Request timeout in seconds |
compression |
false |
Enable gzip compression |
apiVersion |
v0 |
API version |
httpClient |
auto-discovered | Custom PSR-18 HTTP client |
retryMaxRetries |
3 |
Maximum retry attempts |
retryDelayMs |
2000 |
Initial retry delay (ms) |
retryBackoffMultiplier |
2 |
Backoff multiplier |
| Endpoint | Methods |
|---|---|
analyze() |
analyzeContent(), analyzeRecords(), analyzeUrl() |
events() |
send(), sendRaw(), sendJson() |
dataSources() |
list(), retrieve(), quarantine() |
query() |
sql(), batchSql() |
pipes() |
list(), retrieve(), query(), batchQuery(), getData(), explain() |
jobs() |
list(), retrieve(), cancel() |
variables() |
list(), retrieve(), create(), update(), remove() |
tokens() |
list(), retrieve(), create(), createJwt(), update(), refresh(), remove() |
sinkPipes() |
create(), remove(), trigger(), getS3Settings(), getGcsCredentials() |
See the examples directory for complete working examples:
- Quick Start — Basic SDK usage
- Analyze API — Schema inference
- Batch Queries — Concurrent query execution
- Data Sources — List and inspect Data Sources
- Events API — High-frequency ingestion
- Jobs API — Monitor background jobs
- Pipes API — Query API Endpoints
- Tokens API — Token management
- Variables API — Environment variables
Contributions are welcome! See CONTRIBUTING.md.