macropage / idealo-business-api
idealo Business Click API SDK based on Saloon PHP
Package info
github.com/michabbb/idealo-business-api-php-sdk
pkg:composer/macropage/idealo-business-api
Requires
- php: ^8.2
- saloonphp/saloon: ^4.0
Requires (Dev)
- erickskrauch/php-cs-fixer-custom-fixers: ^1.3
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- rector/rector: ^2.4
README
PHP SDK for the idealo Business Click Report API, built on Saloon PHP.
Implements the V2 Detailed Click Report flow only. The deprecated V1 Detailed Click Report (planned shutdown 2026-03-15) is intentionally not included.
Requirements
- PHP
^8.2 saloonphp/saloon^4.0- A pair of idealo Business API credentials (
client_id+client_secret)
Installation
composer require macropage/idealo-business-api
Quick Start
The SDK reads no env vars itself. Wire your own config:
use IdealoBusiness\IdealoBusinessConnector; use IdealoBusiness\Data\ClickReportStatus; $idealo = new IdealoBusinessConnector( clientId: getenv('IDEALO_CLIENT_ID'), clientSecret: getenv('IDEALO_CLIENT_SECRET'), ); // First request triggers auto-auth via boot(). You can also call it explicitly: $idealo->authenticateWithClientCredentials(); // idealo returns the shop_id directly in the token response for single-shop credentials: $shopId = $idealo->getAuthenticatedShopId();
Auth
- Endpoint:
POST /api/v1/oauth/token - Auth: HTTP Basic (
client_id:client_secret) - No request body
- Response fields used by the SDK:
access_token,expires_in,scope,shop_id
The connector caches the token internally. boot() re-authenticates automatically when the token has expired (with a 60-second safety buffer).
Detailed Click Report V2 Flow
The full flow is start → poll → download.
1. Start a report
$response = $idealo->clickReports()->start( shopId: $shopId, from: '2026-04-20', // YYYY-MM-DD, optional to: '2026-04-22', // YYYY-MM-DD, optional ); $data = $response->json(); // $data = ['status' => 'PROCESSING', 'startTime' => '...', 'id' => '<uuid>', // 'shopId' => 12345, 'from' => '2026-04-20', 'to' => '2026-04-22'] $reportId = $data['id'];
HTTP 201 Created on success. endTime is not present while status is PROCESSING.
2. Poll status
$response = $idealo->clickReports()->get($shopId, $reportId); $data = $response->json(); $status = ClickReportStatus::from($data['status']); // ClickReportStatus::Processing | Failed | Successful
Poll responsibly. The SDK ships no built-in polling helper on purpose, so you stay in control of intervals and retries.
3. Download (when SUCCESSFUL)
The download response is a ZIP archive containing one CSV file. The SDK does not decompress or parse it.
$response = $idealo->clickReports()->download($shopId, $reportId); // Always treat this as binary. Do NOT call ->json(). file_put_contents("report_{$reportId}.zip", $response->body());
Server filename pattern: click-cost-report_{shopId}_{YYYY-MM-DD-HH-MM-SS}.csv.zip.
Inspect with PHP's ZipArchive:
$zip = new ZipArchive(); $zip->open("report_{$reportId}.zip"); $csv = $zip->getFromIndex(0);
CSV Columns (Detailed V2)
In order:
Date, Product, idealo Product ID, Category, Customer-IP, Click Type, Site/Partner, Link, Sku, EANs, Cpc
Customer-IPis hashed.EANsmay contain one or more GTIN values.Cpcis the cost per click (decimal).Click Typedistinguishes regularofferclicks from low-price-inventory clicks. See the official docs for the full list.
Limits and Date Rules
- 5 requests per 24 hours to
start()per shop. - At least 15 minutes between two
start()calls. - The report covers data up to 15 months in the past, but never including today.
- Previous-day data is typically available from ~05:00 UTC.
- Exceeding the limits returns HTTP 429.
Error Handling
The connector uses AlwaysThrowOnErrors. Non-2xx responses throw Saloon\Exceptions\Request\RequestException. Common ones:
| Status | Meaning |
|---|---|
409 Conflict |
A report is already in progress for this shop. |
429 Too Many Requests |
Rate limit reached (5/24h or 15-min minimum). |
Connector API
$idealo = new IdealoBusinessConnector($clientId, $clientSecret); // Optional 3rd arg: $baseUrl (defaults to https://businessapi.idealo.com) $idealo->authenticateWithClientCredentials(): self $idealo->getAuthenticatedShopId(): ?int // from token response $idealo->getTokenScope(): ?string $idealo->getTokenType(): ?string $idealo->clickReports()->start(int $shopId, ?string $from = null, ?string $to = null): Response $idealo->clickReports()->get(int $shopId, string $reportId): Response $idealo->clickReports()->download(int $shopId, string $reportId): Response
Deprecated and Out of Scope
- Detailed Click Report V1 (
/api/v1/shops/{shopId}/click-reports) — discontinued 2026-03-15, not implemented. - Daily Click Report — exists at
/api/v1/shops/{shopId}/daily-click-reports/downloadand is not yet covered by this SDK. - The SDK does not decompress ZIPs, parse CSV, validate dates, or poll automatically. Those are application concerns.