Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .fern/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
}
}
},
"sdkVersion": "45.1.0.20260520"
"sdkVersion": "45.2.0.20260520"
}
1 change: 1 addition & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ phpstan.neon
src/Exceptions/SquareApiException.php
src/Legacy
src/Utils/WebhooksHelper.php
src/Utils/ReportingHelper.php
tests/Integration
.fern/replay.lock
.fern/replay.yml
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
runs-on: ubuntu-latest
env:
TEST_SQUARE_TOKEN: ${{ secrets.TEST_SQUARE_TOKEN }}
TEST_SQUARE_REPORTING: ${{ secrets.TEST_SQUARE_REPORTING }}

steps:
- name: Checkout repo
Expand Down
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,77 @@ $isValid = WebhooksHelper.verifySignature(
)
```

## Reporting API

The [Square Reporting API](https://developer.squareup.com/docs/reporting-api/overview) lets you
query aggregated business data. Start by calling `getMetadata` to discover the schema — the cubes,
views, measures, dimensions, and segments you can reference — then run a query with `load`:

```php
$metadata = $client->reporting->getMetadata();

$response = $client->reporting->load(new Square\Reporting\Requests\LoadRequest([
'query' => new Square\Types\Query([
'measures' => ['Orders.count'],
]),
]));
```

### Polling for long-running queries

The `load` endpoint is asynchronous. While a query is still being computed, the API responds with
an HTTP `200` whose body is `{ "error": "Continue wait" }` instead of results, and the client is
expected to re-send the identical request until the results are ready. The SDK provides
`ReportingHelper::loadAndWait`, which owns that retry loop with exponential backoff:

```php
use Square\Utils\ReportingHelper;
use Square\Reporting\Requests\LoadRequest;
use Square\Types\Query;

$response = ReportingHelper::loadAndWait(
$client,
new LoadRequest([
'query' => new Query([
'measures' => ['Orders.count'],
]),
]),
);

foreach ($response->getResults() as $result) {
// ...
}
```

`loadAndWait` accepts an options array to tune the polling behavior:

| Option | Default | Description |
| --- | --- | --- |
| `maxAttempts` | `20` | Maximum poll attempts before giving up. |
| `initialDelayMs` | `2000` | Delay before the first retry, in milliseconds. |
| `maxDelayMs` | `20000` | Upper bound on the backoff delay, in milliseconds. |
| `backoffFactor` | `2` | Multiplier applied to the delay after each attempt. |
| `shouldCancel` | `null` | A `callable(): bool` polled before each attempt (and during the wait); aborts the loop when it returns `true`. |
| `requestOptions` | `null` | Per-request options forwarded to each underlying `reporting->load` call. |

```php
$response = ReportingHelper::loadAndWait(
$client,
new LoadRequest([/* ... */]),
[
'maxAttempts' => 30,
'initialDelayMs' => 1000,
'shouldCancel' => fn (): bool => /* e.g. a deadline check */ false,
],
);
```

If the query does not resolve within `maxAttempts`, or if `shouldCancel` aborts it, a
`Square\Exceptions\SquareException` is thrown.

> **Note:** The Reporting API is available in **production only** and requires a
> reporting-provisioned access token; it is not available in the sandbox environment.

## Legacy SDK

While the new SDK has a lot of improvements, we at Square understand that it takes time to upgrade when there are breaking changes.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "square/square",
"version": "45.1.0.20260520",
"version": "45.2.0.20260520",
"description": "Use Square APIs to manage and run business including payment, customer, product, inventory, and employee management.",
"keywords": [
"square",
Expand Down
112 changes: 112 additions & 0 deletions reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -16007,6 +16007,118 @@ $client->vendors->update(
</dl>


</dd>
</dl>
</details>

## Reporting
<details><summary><code>$client-&gt;reporting-&gt;getMetadata() -> MetadataResponse</code></summary>
<dl>
<dd>

#### 📝 Description

<dl>
<dd>

<dl>
<dd>

Describes the data available to query: the cubes, views, measures, dimensions, and segments you can reference in a reporting query. Call this first to discover the schema, then pass the members you need to `load`.
</dd>
</dl>
</dd>
</dl>

#### 🔌 Usage

<dl>
<dd>

<dl>
<dd>

```php
$client->reporting->getMetadata();
```
</dd>
</dl>
</dd>
</dl>


</dd>
</dl>
</details>

<details><summary><code>$client-&gt;reporting-&gt;load($request) -> LoadResponse</code></summary>
<dl>
<dd>

#### 📝 Description

<dl>
<dd>

<dl>
<dd>

Runs a reporting query against the discovered schema and returns the aggregated results. Long-running queries may return a "Continue wait" response while processing — retry the same request until results are ready.
</dd>
</dl>
</dd>
</dl>

#### 🔌 Usage

<dl>
<dd>

<dl>
<dd>

```php
$client->reporting->load(
new LoadRequest([]),
);
```
</dd>
</dl>
</dd>
</dl>

#### ⚙️ Parameters

<dl>
<dd>

<dl>
<dd>

**$queryType:** `?string`

</dd>
</dl>

<dl>
<dd>

**$cache:** `?string`

</dd>
</dl>

<dl>
<dd>

**$query:** `?Query`

</dd>
</dl>
</dd>
</dl>


</dd>
</dl>
</details>
Expand Down
143 changes: 143 additions & 0 deletions src/Reporting/ReportingClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

namespace Square\Reporting;

use Psr\Http\Client\ClientInterface;
use Square\Core\Client\RawClient;
use Square\Types\MetadataResponse;
use Square\Exceptions\SquareException;
use Square\Exceptions\SquareApiException;
use Square\Core\Json\JsonApiRequest;
use Square\Environments;
use Square\Core\Client\HttpMethod;
use JsonException;
use Psr\Http\Client\ClientExceptionInterface;
use Square\Reporting\Requests\LoadRequest;
use Square\Types\LoadResponse;

class ReportingClient
{
/**
* @var array{
* baseUrl?: string,
* client?: ClientInterface,
* maxRetries?: int,
* timeout?: float,
* headers?: array<string, string>,
* } $options @phpstan-ignore-next-line Property is used in endpoint methods via HttpEndpointGenerator
*/
private array $options;

/**
* @var RawClient $client
*/
private RawClient $client;

/**
* @param RawClient $client
* @param ?array{
* baseUrl?: string,
* client?: ClientInterface,
* maxRetries?: int,
* timeout?: float,
* headers?: array<string, string>,
* } $options
*/
public function __construct(
RawClient $client,
?array $options = null,
) {
$this->client = $client;
$this->options = $options ?? [];
}

/**
* Describes the data available to query: the cubes, views, measures, dimensions, and segments you can reference in a reporting query. Call this first to discover the schema, then pass the members you need to `load`.
*
* @param ?array{
* baseUrl?: string,
* maxRetries?: int,
* timeout?: float,
* headers?: array<string, string>,
* queryParameters?: array<string, mixed>,
* bodyProperties?: array<string, mixed>,
* } $options
* @return MetadataResponse
* @throws SquareException
* @throws SquareApiException
*/
public function getMetadata(?array $options = null): MetadataResponse
{
$options = array_merge($this->options, $options ?? []);
try {
$response = $this->client->sendRequest(
new JsonApiRequest(
baseUrl: $options['baseUrl'] ?? $this->client->options['baseUrl'] ?? Environments::Production->value,
path: "reporting/v1/meta",
method: HttpMethod::GET,
),
$options,
);
$statusCode = $response->getStatusCode();
if ($statusCode >= 200 && $statusCode < 400) {
$json = $response->getBody()->getContents();
return MetadataResponse::fromJson($json);
}
} catch (JsonException $e) {
throw new SquareException(message: "Failed to deserialize response: {$e->getMessage()}", previous: $e);
} catch (ClientExceptionInterface $e) {
throw new SquareException(message: $e->getMessage(), previous: $e);
}
throw new SquareApiException(
message: 'API request failed',
statusCode: $statusCode,
body: $response->getBody()->getContents(),
);
}

/**
* Runs a reporting query against the discovered schema and returns the aggregated results. Long-running queries may return a "Continue wait" response while processing — retry the same request until results are ready.
*
* @param LoadRequest $request
* @param ?array{
* baseUrl?: string,
* maxRetries?: int,
* timeout?: float,
* headers?: array<string, string>,
* queryParameters?: array<string, mixed>,
* bodyProperties?: array<string, mixed>,
* } $options
* @return LoadResponse
* @throws SquareException
* @throws SquareApiException
*/
public function load(LoadRequest $request = new LoadRequest(), ?array $options = null): LoadResponse
{
$options = array_merge($this->options, $options ?? []);
try {
$response = $this->client->sendRequest(
new JsonApiRequest(
baseUrl: $options['baseUrl'] ?? $this->client->options['baseUrl'] ?? Environments::Production->value,
path: "reporting/v1/load",
method: HttpMethod::POST,
body: $request,
),
$options,
);
$statusCode = $response->getStatusCode();
if ($statusCode >= 200 && $statusCode < 400) {
$json = $response->getBody()->getContents();
return LoadResponse::fromJson($json);
}
} catch (JsonException $e) {
throw new SquareException(message: "Failed to deserialize response: {$e->getMessage()}", previous: $e);
} catch (ClientExceptionInterface $e) {
throw new SquareException(message: $e->getMessage(), previous: $e);
}
throw new SquareApiException(
message: 'API request failed',
statusCode: $statusCode,
body: $response->getBody()->getContents(),
);
}
}
Loading
Loading