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/psr7useBrd6\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']);useBrd6\TinybirdSdk\Client;
useBrd6\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:
useBrd6\TinybirdSdk\Client;
useBrd6\TinybirdSdk\ClientOptions;
$options = (newClientOptions())
->setToken('your_token')
->setBaseUrl('https://your-custom-endpoint.com');
$tinybird = newClient($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 columnsforeach ($result->columnsas$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 resultecho$result->successfulRows; // Rows ingestedecho$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 ($datasourcesas$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 columnsforeach ($info->columnsas$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 resultsforeach ($result->dataas$row) {
echo$row['event'];
}
// Query statisticsecho$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 resultsforeach ($resultsas$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->dataas$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 isolationforeach ($resultsas$key => $result) {
if ($result->isSuccess()) {
$data = $result->getData();
echo"{$key}: {$data->rows} rows";
} else {
// Individual failures don't affect other queriesecho"{$key} failed: " . $result->getException()->getMessage();
}
}Monitor and manage background jobs (imports, populates, copies).
useBrd6\TinybirdSdk\RequestParameters\ListJobsParams;
useBrd6\TinybirdSdk\Enum\JobStatus;
// List recent jobs$jobs = $tinybird->jobs()->list();
// Filter by status$jobs = $tinybird->jobs()->list(newListJobsParams(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.
useBrd6\TinybirdSdk\RequestParameters\CreateTokenParams;
// List all tokens$tokens = $tinybird->tokens()->list();
// Create a token with scopes$token = $tinybird->tokens()->create(newCreateTokenParams(
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).
useBrd6\TinybirdSdk\RequestParameters\CreateSinkParams;
// Create a sink pipe$pipe = $tinybird->sinkPipes()->create($pipeId, $nodeId, newCreateSinkParams(
connection: 's3://bucket/path',
path: 'exports/',
));
// Trigger a sink export$result = $tinybird->sinkPipes()->trigger($pipeId);
// Get S3 integration settings$settings = $tinybird->sinkPipes()->getS3Settings();useBrd6\TinybirdSdk\Exception\ApiException;
useBrd6\TinybirdSdk\Exception\AuthenticationException;
useBrd6\TinybirdSdk\Exception\RateLimitException;
useBrd6\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 |
useBrd6\TinybirdSdk\Client;
useBrd6\TinybirdSdk\ClientOptions;
useBrd6\TinybirdSdk\Enum\Region;
$options = (newClientOptions())
->setToken(getenv('TINYBIRD_TOKEN'))
->setRegion(Region::AWS_EU_CENTRAL_1)
->setTimeout(120)
->setCompression(true)
->setRetryMaxRetries(5)
->setRetryDelayMs(1000)
->setRetryBackoffMultiplier(3);
$tinybird = newClient($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.