Skip to content
Merged
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 .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "5.0.0"
".": "5.0.1"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 78
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-b79e0eb1ab06f4076c48fa519e2b2ad792a0c483a5d017e43c938ca4c4be6988.yml
openapi_spec_hash: cb3cc2c1145503e5737a880326857aa4
config_hash: ff903e824043dc81aca51a0ce21896d6
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-e3e54d99e2a73fd87519270f2685131050d342e86a4e96130247b854deae5c20.yml
openapi_spec_hash: 897a3fbee24f24d021d6af0df480220c
config_hash: 66a5c28bb74d78454456d9ce7d1c0a0c
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## 5.0.1 (2026-01-14)

Full Changelog: [v5.0.0...v5.0.1](https://github.com/trycourier/courier-php/compare/v5.0.0...v5.0.1)

### Bug Fixes

* typos in README.md ([f1a033c](https://github.com/trycourier/courier-php/commit/f1a033c8c70d2a48f5fea41af512766957d97923))


### Chores

* fix typo in descriptions ([f46d067](https://github.com/trycourier/courier-php/commit/f46d067a4a66d5a94dde8f4c02621e917c665c32))
* **internal:** codegen related update ([7b4fa3b](https://github.com/trycourier/courier-php/commit/7b4fa3ba45681760ac59e758fa94756246e343ae))
* **internal:** codegen related update ([89591b8](https://github.com/trycourier/courier-php/commit/89591b8dd16a7b9c3f55abac64ad65fef05fb94e))
* **internal:** regenerate SDK with no functional changes ([eb51446](https://github.com/trycourier/courier-php/commit/eb51446e6b4e8368d8e27053d3605d1b089fcac4))
* **internal:** regenerate SDK with no functional changes ([bd1ea2c](https://github.com/trycourier/courier-php/commit/bd1ea2c50e9c8ddee9d51c7ed6e18e30e2dc5e27))
* **readme:** remove beta warning now that we're in ga ([c3d5ef7](https://github.com/trycourier/courier-php/commit/c3d5ef7b9481b5c2762f28cff97610277eb2880f))
* remove custom code ([5b4f359](https://github.com/trycourier/courier-php/commit/5b4f359ac6c2664b81c080dba20e8f6b54629ded))

## 5.0.0 (2026-01-12)

Full Changelog: [v4.1.0...v5.0.0](https://github.com/trycourier/courier-php/compare/v4.1.0...v5.0.0)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2025 Courier
Copyright 2026 Courier

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
# Courier PHP API library

> [!NOTE]
> The Courier PHP API Library is currently in **beta** and we're excited for you to experiment with it!
>
> This library has not yet been exhaustively tested in production environments and may be missing some features you'd expect in a stable release. As we continue development, there may be breaking changes that require updates to your code.
>
> **We'd love your feedback!** Please share any suggestions, bug reports, feature requests, or general thoughts by [filing an issue](https://www.github.com/trycourier/courier-php/issues/new).

The Courier PHP library provides convenient access to the Courier REST API from any PHP 8.1.0+ application.

It is generated with [Stainless](https://www.stainless.com/).
Expand Down Expand Up @@ -75,6 +68,8 @@ When the library is unable to connect to the API, or if the API returns a non-su
<?php

use Courier\Core\Exceptions\APIConnectionException;
use Courier\Core\Exceptions\RateLimitException;
use Courier\Core\Exceptions\APIStatusException;

try {
$response = $client->send->message(
Expand All @@ -87,9 +82,9 @@ try {
} catch (APIConnectionException $e) {
echo "The server could not be reached", PHP_EOL;
var_dump($e->getPrevious());
} catch (RateLimitError $e) {
} catch (RateLimitException $e) {
echo "A 429 status code was received; we should back off a bit.", PHP_EOL;
} catch (APIStatusError $e) {
} catch (APIStatusException $e) {
echo "Another non-200-range status code was received", PHP_EOL;
echo $e->getMessage();
}
Expand Down
76 changes: 76 additions & 0 deletions src/AudienceFilterConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace Courier;

use Courier\Core\Attributes\Required;
use Courier\Core\Concerns\SdkModel;
use Courier\Core\Contracts\BaseModel;

/**
* Filter configuration for audience membership containing an array of filter rules.
*
* @phpstan-type AudienceFilterConfigShape = array{filters: list<mixed>}
*/
final class AudienceFilterConfig implements BaseModel
{
/** @use SdkModel<AudienceFilterConfigShape> */
use SdkModel;

/**
* Array of filter rules (single conditions or nested groups).
*
* @var list<mixed> $filters
*/
#[Required(list: FilterConfig::class)]
public array $filters;

/**
* `new AudienceFilterConfig()` is missing required properties by the API.
*
* To enforce required parameters use
* ```
* AudienceFilterConfig::with(filters: ...)
* ```
*
* Otherwise ensure the following setters are called
*
* ```
* (new AudienceFilterConfig)->withFilters(...)
* ```
*/
public function __construct()
{
$this->initialize();
}

/**
* Construct an instance from the required parameters.
*
* You must use named parameters to construct any parameters with a default value.
*
* @param list<mixed> $filters
*/
public static function with(array $filters): self
{
$self = new self;

$self['filters'] = $filters;

return $self;
}

/**
* Array of filter rules (single conditions or nested groups).
*
* @param list<mixed> $filters
*/
public function withFilters(array $filters): self
{
$self = clone $this;
$self['filters'] = $filters;

return $self;
}
}
85 changes: 52 additions & 33 deletions src/Audiences/Audience.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@

namespace Courier\Audiences;

use Courier\AudienceFilterConfig;
use Courier\Audiences\Audience\Operator;
use Courier\Core\Attributes\Optional;
use Courier\Core\Attributes\Required;
use Courier\Core\Concerns\SdkModel;
use Courier\Core\Contracts\BaseModel;

/**
* @phpstan-import-type FilterVariants from \Courier\Audiences\Filter
* @phpstan-import-type FilterShape from \Courier\Audiences\Filter
* @phpstan-import-type AudienceFilterConfigShape from \Courier\AudienceFilterConfig
*
* @phpstan-type AudienceShape = array{
* id: string,
* createdAt: string,
* description: string,
* filter: FilterShape,
* name: string,
* updatedAt: string,
* filter?: null|AudienceFilterConfig|AudienceFilterConfigShape,
* operator?: null|Operator|value-of<Operator>,
* }
*/
final class Audience implements BaseModel
Expand All @@ -41,14 +44,6 @@ final class Audience implements BaseModel
#[Required]
public string $description;

/**
* A single filter to use for filtering.
*
* @var FilterVariants $filter
*/
#[Required]
public SingleFilterConfig|NestedFilterConfig $filter;

/**
* The name of the audience.
*/
Expand All @@ -58,18 +53,27 @@ final class Audience implements BaseModel
#[Required('updated_at')]
public string $updatedAt;

/**
* Filter configuration for audience membership containing an array of filter rules.
*/
#[Optional(nullable: true)]
public ?AudienceFilterConfig $filter;

/**
* The logical operator (AND/OR) for the top-level filter.
*
* @var value-of<Operator>|null $operator
*/
#[Optional(enum: Operator::class)]
public ?string $operator;

/**
* `new Audience()` is missing required properties by the API.
*
* To enforce required parameters use
* ```
* Audience::with(
* id: ...,
* createdAt: ...,
* description: ...,
* filter: ...,
* name: ...,
* updatedAt: ...,
* id: ..., createdAt: ..., description: ..., name: ..., updatedAt: ...
* )
* ```
*
Expand All @@ -80,7 +84,6 @@ final class Audience implements BaseModel
* ->withID(...)
* ->withCreatedAt(...)
* ->withDescription(...)
* ->withFilter(...)
* ->withName(...)
* ->withUpdatedAt(...)
* ```
Expand All @@ -95,25 +98,29 @@ public function __construct()
*
* You must use named parameters to construct any parameters with a default value.
*
* @param FilterShape $filter
* @param AudienceFilterConfig|AudienceFilterConfigShape|null $filter
* @param Operator|value-of<Operator>|null $operator
*/
public static function with(
string $id,
string $createdAt,
string $description,
SingleFilterConfig|array|NestedFilterConfig $filter,
string $name,
string $updatedAt,
AudienceFilterConfig|array|null $filter = null,
Operator|string|null $operator = null,
): self {
$self = new self;

$self['id'] = $id;
$self['createdAt'] = $createdAt;
$self['description'] = $description;
$self['filter'] = $filter;
$self['name'] = $name;
$self['updatedAt'] = $updatedAt;

null !== $filter && $self['filter'] = $filter;
null !== $operator && $self['operator'] = $operator;

return $self;
}

Expand Down Expand Up @@ -148,34 +155,46 @@ public function withDescription(string $description): self
}

/**
* A single filter to use for filtering.
*
* @param FilterShape $filter
* The name of the audience.
*/
public function withFilter(
SingleFilterConfig|array|NestedFilterConfig $filter
): self {
public function withName(string $name): self
{
$self = clone $this;
$self['filter'] = $filter;
$self['name'] = $name;

return $self;
}

public function withUpdatedAt(string $updatedAt): self
{
$self = clone $this;
$self['updatedAt'] = $updatedAt;

return $self;
}

/**
* The name of the audience.
* Filter configuration for audience membership containing an array of filter rules.
*
* @param AudienceFilterConfig|AudienceFilterConfigShape|null $filter
*/
public function withName(string $name): self
public function withFilter(AudienceFilterConfig|array|null $filter): self
{
$self = clone $this;
$self['name'] = $name;
$self['filter'] = $filter;

return $self;
}

public function withUpdatedAt(string $updatedAt): self
/**
* The logical operator (AND/OR) for the top-level filter.
*
* @param Operator|value-of<Operator> $operator
*/
public function withOperator(Operator|string $operator): self
{
$self = clone $this;
$self['updatedAt'] = $updatedAt;
$self['operator'] = $operator;

return $self;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Audiences/Audience/Operator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Courier\Audiences\Audience;

/**
* The logical operator (AND/OR) for the top-level filter.
*/
enum Operator: string
{
case AND = 'AND';

case OR = 'OR';
}
Loading
Loading