errorCode = $errorCode; $this->responseHeaders = $responseHeaders; } public function getErrorCode(): ?string { return $this->errorCode; } public function getHttpStatus(): int { return (int) $this->getCode(); } public function getResponseHeaders(): array { return $this->responseHeaders; } } class SattazAuthException extends SattazApiException {} class SattazRateLimitException extends SattazApiException {} /** * Sattaz Official PHP SDK Client * * Lightweight, zero-dependency client for accessing the Sattaz Commercial Results & Charts API. */ class SattazClient { private string $apiKey; private string $baseUrl; private int $timeout; /** * @param string $apiKey The API Key (starts with stz_live_...) * @param string $baseUrl Optional custom API base URL * @param int $timeout cURL timeout in seconds */ public function __construct(string $apiKey, string $baseUrl = 'https://sattaz.com/api/v1', int $timeout = 10) { $this->apiKey = trim($apiKey); $this->baseUrl = rtrim($baseUrl, '/'); $this->timeout = $timeout; } /** * Get directory of all available markets. * * @param string|null $category Filter by category: 'matka', 'kolkataff', or 'satta' * @return array */ public function getMarkets(?string $category = null): array { $params = []; if ($category !== null) { $params['category'] = $category; } return $this->request('GET', '/markets', $params); } /** * Get today's live declared results across all markets. * Response is served with sub-millisecond latency from high-speed in-memory cache. * * @param string|null $category Filter by category: 'matka', 'kolkataff', or 'satta' * @return array */ public function getLiveResults(?string $category = null): array { $params = []; if ($category !== null) { $params['category'] = $category; } return $this->request('GET', '/results/live', $params); } /** * Get all Regular Matka results for today or a specific historical date. * * @param string|null $date Format YYYY-MM-DD (defaults to today) * @return array */ public function getMatkaResults(?string $date = null): array { $params = $date !== null ? ['date' => $date] : []; return $this->request('GET', '/results/matka', $params); } /** * Get all Satta King results for today or a specific historical date. * * @param string|null $date Format YYYY-MM-DD (defaults to today) * @return array */ public function getSattaResults(?string $date = null): array { $params = $date !== null ? ['date' => $date] : []; return $this->request('GET', '/results/satta', $params); } /** * Get Kolkata FF bazis/rounds for today or a specific historical date. * * @param string|null $date Format YYYY-MM-DD (defaults to today) * @return array */ public function getKolkataFfResults(?string $date = null): array { $params = $date !== null ? ['date' => $date] : []; return $this->request('GET', '/results/kolkataff', $params); } /** * Get results of all markets for a specific category and date. * * @param string $category 'matka', 'satta', or 'kolkataff' * @param string|null $date Format YYYY-MM-DD (defaults to today) * @return array */ public function getCategoryResults(string $category, ?string $date = null): array { $params = $date !== null ? ['date' => $date] : []; return $this->request('GET', '/results/' . rawurlencode($category), $params); } /** * Get latest result or query older date results for a specific market. * * @param string $marketSlug Slug of market (e.g. 'kalyan', 'milan-day', 'kolkata-ff') * @param string|null $date Specific date query (format YYYY-MM-DD) * @param array $options Additional options: 'from', 'to', 'limit' * @return array */ public function getMarketResult(string $marketSlug, ?string $date = null, array $options = []): array { $params = $options; if ($date !== null) { $params['date'] = $date; } return $this->request('GET', '/results/' . rawurlencode($marketSlug), $params); } /** * Get full panel chart history for a market. * * @param string $marketSlug Slug of market (e.g. 'kalyan', 'milan-day') * @param array $options Options: 'year' (e.g. 2026), 'from', 'to', 'limit' (max 1000) * @return array */ public function getMarketChart(string $marketSlug, array $options = []): array { return $this->request('GET', '/charts/' . rawurlencode($marketSlug), $options); } /** * Convenient helper to get chart by year and limit. * * @param string $marketSlug * @param int|null $year * @param int $limit * @return array */ public function getChart(string $marketSlug, ?int $year = null, int $limit = 500): array { $options = ['limit' => $limit]; if ($year !== null) { $options['year'] = $year; } return $this->getMarketChart($marketSlug, $options); } /** * Check API key status, tier, quota usage, and expiration. * * @return array */ public function getUsage(): array { return $this->request('GET', '/usage'); } /** * Low-level HTTP requester using PHP cURL */ private function request(string $method, string $path, array $queryParams = []): array { $url = $this->baseUrl . $path; if (!empty($queryParams)) { $url .= '?' . http_build_query($queryParams); } $headers = [ 'Authorization: Bearer ' . $this->apiKey, 'Accept: application/json', 'User-Agent: Sattaz-PHP-SDK/1.0' ]; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_HEADER => true, CURLOPT_FOLLOWLOCATION => true ]); $rawResponse = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $curlError = curl_error($ch); curl_close($ch); if ($rawResponse === false) { throw new SattazApiException("Connection error: $curlError", 0); } $headerStr = substr($rawResponse, 0, $headerSize); $bodyStr = substr($rawResponse, $headerSize); $responseHeaders = $this->parseHeaders($headerStr); $json = json_decode($bodyStr, true); if ($json === null && !empty($bodyStr)) { throw new SattazApiException("Invalid JSON response from server: $bodyStr", $httpCode, null, $responseHeaders); } if ($httpCode === 401) { $msg = $json['message'] ?? 'Authentication failed. Check your API key.'; throw new SattazAuthException($msg, 401, $json['code'] ?? 'unauthorized', $responseHeaders); } if ($httpCode === 429) { $msg = $json['message'] ?? 'Rate limit exceeded.'; throw new SattazRateLimitException($msg, 429, 'rate_limit_exceeded', $responseHeaders); } if ($httpCode >= 400) { $msg = $json['message'] ?? "API error (HTTP $httpCode)"; $code = $json['code'] ?? 'api_error'; throw new SattazApiException($msg, $httpCode, $code, $responseHeaders); } return $json['data'] ?? $json; } private function parseHeaders(string $headerStr): array { $headers = []; $lines = explode("\r\n", $headerStr); foreach ($lines as $line) { if (strpos($line, ':') !== false) { list($key, $val) = explode(':', $line, 2); $headers[trim($key)] = trim($val); } } return $headers; } }