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 @@
{
".": "0.4.0"
".": "0.5.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 17
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-56b0f699c5437d9e5326626d35dfc972c17d01f12cb416c7f4854c8ea6d0e95e.yml
openapi_spec_hash: 158f405c1880706266d83e6ff16b9d2f
config_hash: 41c337f5cda03b13880617490f82bad0
configured_endpoints: 21
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-d9763d006969b49a1473851069fdfa429eb13133b64103a62963bb70ddb22305.yml
openapi_spec_hash: 6aee689b7a759b12c85c088c15e29bc0
config_hash: 4ab3e1ee76a463e0ed214541260ee12e
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## 0.5.0 (2026-02-23)

Full Changelog: [v0.4.0...v0.5.0](https://github.com/CASParser/cas-parser-php/compare/v0.4.0...v0.5.0)

### Features

* **api:** api update ([d8c85b9](https://github.com/CASParser/cas-parser-php/commit/d8c85b904f3df1c7242527d1dd66996d0e8cd6e8))
* **api:** api update ([92b50de](https://github.com/CASParser/cas-parser-php/commit/92b50de8ea771c015e38a2635f1ee5c011156008))
* **api:** api update ([c0fc7b8](https://github.com/CASParser/cas-parser-php/commit/c0fc7b8b4284930ca1d6eec4c58e88b026cf2da5))
* **api:** manual updates ([83a811c](https://github.com/CASParser/cas-parser-php/commit/83a811cd2ac157f781caeabff6e8e0f4b757435e))


### Chores

* **internal:** remove mock server code ([e868489](https://github.com/CASParser/cas-parser-php/commit/e8684893f2f7c4ab6d75c2be56fc9f2d7c6a5323))
* update mock server docs ([8a17bde](https://github.com/CASParser/cas-parser-php/commit/8a17bdee09cb200c74522cdf7ed35f8934ba4ecd))

## 0.4.0 (2026-02-14)

Full Changelog: [v0.3.0...v0.4.0](https://github.com/CASParser/cas-parser-php/compare/v0.3.0...v0.4.0)
Expand Down
41 changes: 0 additions & 41 deletions scripts/mock

This file was deleted.

46 changes: 0 additions & 46 deletions scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,6 @@ set -e

cd "$(dirname "$0")/.."

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

function prism_is_running() {
curl --silent "http://localhost:4010" >/dev/null 2>&1
}

kill_server_on_port() {
pids=$(lsof -t -i tcp:"$1" || echo "")
if [ "$pids" != "" ]; then
kill "$pids"
echo "Stopped $pids."
fi
}

function is_overriding_api_base_url() {
[ -n "$TEST_API_BASE_URL" ]
}

if ! is_overriding_api_base_url && ! prism_is_running ; then
# When we exit this script, make sure to kill the background mock server process
trap 'kill_server_on_port 4010' EXIT

# Start the dev server
./scripts/mock --daemon
fi

if is_overriding_api_base_url ; then
echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}"
echo
elif ! prism_is_running ; then
echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server"
echo -e "running against your OpenAPI spec."
echo
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the prism command:"
echo
echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}"
echo

exit 1
else
echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}"
echo
fi

exec -- ./vendor/bin/pest --colors=always
2 changes: 2 additions & 0 deletions src/AccessToken/AccessTokenCreateParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*
* **Use this endpoint from your backend** to create tokens that can be safely passed to frontend/SDK.
*
* **Legacy path:** `/v1/access-token` (still supported)
*
* Access tokens:
* - Are prefixed with `at_` for easy identification
* - Valid for up to 60 minutes
Expand Down
7 changes: 7 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use CasParser\Services\CdslService;
use CasParser\Services\ContractNoteService;
use CasParser\Services\CreditsService;
use CasParser\Services\InboundEmailService;
use CasParser\Services\InboxService;
use CasParser\Services\KfintechService;
use CasParser\Services\LogsService;
Expand Down Expand Up @@ -83,6 +84,11 @@ class Client extends BaseClient
*/
public SmartService $smart;

/**
* @api
*/
public InboundEmailService $inboundEmail;

/**
* @param RequestOpts|null $requestOptions
*/
Expand Down Expand Up @@ -134,6 +140,7 @@ public function __construct(
$this->kfintech = new KfintechService($this);
$this->nsdl = new NsdlService($this);
$this->smart = new SmartService($this);
$this->inboundEmail = new InboundEmailService($this);
}

/** @return array<string,string> */
Expand Down
208 changes: 208 additions & 0 deletions src/InboundEmail/InboundEmailCreateParams.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
<?php

declare(strict_types=1);

namespace CasParser\InboundEmail;

use CasParser\Core\Attributes\Optional;
use CasParser\Core\Attributes\Required;
use CasParser\Core\Concerns\SdkModel;
use CasParser\Core\Concerns\SdkParams;
use CasParser\Core\Contracts\BaseModel;
use CasParser\InboundEmail\InboundEmailCreateParams\AllowedSource;

/**
* Create a dedicated inbound email address for collecting CAS statements via email forwarding.
*
* **How it works:**
* 1. Create an inbound email with your webhook URL
* 2. Display the email address to your user (e.g., "Forward your CAS to ie_xxx@import.casparser.in")
* 3. When an investor forwards a CAS email, we verify the sender and deliver to your webhook
*
* **Webhook Delivery:**
* - We POST to your `callback_url` with JSON body containing files (matching EmailCASFile schema)
* - Failed deliveries are retried automatically with exponential backoff
*
* **Inactivity:**
* - Inbound emails with no activity in 30 days are marked inactive
* - Active inbound emails remain operational indefinitely
*
* @see CasParser\Services\InboundEmailService::create()
*
* @phpstan-type InboundEmailCreateParamsShape = array{
* callbackURL: string,
* alias?: string|null,
* allowedSources?: list<AllowedSource|value-of<AllowedSource>>|null,
* metadata?: array<string,string>|null,
* reference?: string|null,
* }
*/
final class InboundEmailCreateParams implements BaseModel
{
/** @use SdkModel<InboundEmailCreateParamsShape> */
use SdkModel;
use SdkParams;

/**
* Webhook URL where we POST email notifications.
* Must be HTTPS in production (HTTP allowed for localhost during development).
*/
#[Required('callback_url')]
public string $callbackURL;

/**
* Optional custom email prefix for user-friendly addresses.
* - Must be 3-32 characters
* - Alphanumeric + hyphens only
* - Must start and end with letter/number
* - Example: `john-portfolio@import.casparser.in`
* - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in`.
*/
#[Optional]
public ?string $alias;

/**
* Filter emails by CAS provider. If omitted, accepts all providers.
* - `cdsl` → eCAS@cdslstatement.com
* - `nsdl` → NSDL-CAS@nsdl.co.in
* - `cams` → donotreply@camsonline.com
* - `kfintech` → samfS@kfintech.com.
*
* @var list<value-of<AllowedSource>>|null $allowedSources
*/
#[Optional('allowed_sources', list: AllowedSource::class)]
public ?array $allowedSources;

/**
* Optional key-value pairs (max 10) to include in webhook payload.
* Useful for passing context like plan_type, campaign_id, etc.
*
* @var array<string,string>|null $metadata
*/
#[Optional(map: 'string')]
public ?array $metadata;

/**
* Your internal identifier (e.g., user_id, account_id).
* Returned in webhook payload for correlation.
*/
#[Optional]
public ?string $reference;

/**
* `new InboundEmailCreateParams()` is missing required properties by the API.
*
* To enforce required parameters use
* ```
* InboundEmailCreateParams::with(callbackURL: ...)
* ```
*
* Otherwise ensure the following setters are called
*
* ```
* (new InboundEmailCreateParams)->withCallbackURL(...)
* ```
*/
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<AllowedSource|value-of<AllowedSource>>|null $allowedSources
* @param array<string,string>|null $metadata
*/
public static function with(
string $callbackURL,
?string $alias = null,
?array $allowedSources = null,
?array $metadata = null,
?string $reference = null,
): self {
$self = new self;

$self['callbackURL'] = $callbackURL;

null !== $alias && $self['alias'] = $alias;
null !== $allowedSources && $self['allowedSources'] = $allowedSources;
null !== $metadata && $self['metadata'] = $metadata;
null !== $reference && $self['reference'] = $reference;

return $self;
}

/**
* Webhook URL where we POST email notifications.
* Must be HTTPS in production (HTTP allowed for localhost during development).
*/
public function withCallbackURL(string $callbackURL): self
{
$self = clone $this;
$self['callbackURL'] = $callbackURL;

return $self;
}

/**
* Optional custom email prefix for user-friendly addresses.
* - Must be 3-32 characters
* - Alphanumeric + hyphens only
* - Must start and end with letter/number
* - Example: `john-portfolio@import.casparser.in`
* - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in`.
*/
public function withAlias(string $alias): self
{
$self = clone $this;
$self['alias'] = $alias;

return $self;
}

/**
* Filter emails by CAS provider. If omitted, accepts all providers.
* - `cdsl` → eCAS@cdslstatement.com
* - `nsdl` → NSDL-CAS@nsdl.co.in
* - `cams` → donotreply@camsonline.com
* - `kfintech` → samfS@kfintech.com.
*
* @param list<AllowedSource|value-of<AllowedSource>> $allowedSources
*/
public function withAllowedSources(array $allowedSources): self
{
$self = clone $this;
$self['allowedSources'] = $allowedSources;

return $self;
}

/**
* Optional key-value pairs (max 10) to include in webhook payload.
* Useful for passing context like plan_type, campaign_id, etc.
*
* @param array<string,string> $metadata
*/
public function withMetadata(array $metadata): self
{
$self = clone $this;
$self['metadata'] = $metadata;

return $self;
}

/**
* Your internal identifier (e.g., user_id, account_id).
* Returned in webhook payload for correlation.
*/
public function withReference(string $reference): self
{
$self = clone $this;
$self['reference'] = $reference;

return $self;
}
}
16 changes: 16 additions & 0 deletions src/InboundEmail/InboundEmailCreateParams/AllowedSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace CasParser\InboundEmail\InboundEmailCreateParams;

enum AllowedSource: string
{
case CDSL = 'cdsl';

case NSDL = 'nsdl';

case CAMS = 'cams';

case KFINTECH = 'kfintech';
}
Loading