https://github.com/trycourier/courier-csharp
https://github.com/trycourier/courier-csharp
Last synced: 6 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/trycourier/courier-csharp
- Owner: trycourier
- License: apache-2.0
- Created: 2024-03-04T21:07:40.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-01-10T04:19:16.000Z (7 months ago)
- Last Synced: 2026-01-11T01:17:54.672Z (7 months ago)
- Language: C#
- Size: 2.24 MB
- Stars: 1
- Watchers: 2
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Courier C# API Library
The Courier C# SDK provides convenient access to the [Courier REST API](https://www.courier.com/docs) from applications written in C#.
It is generated with [Stainless](https://www.stainless.com/).
The REST API documentation can be found on [www.courier.com](https://www.courier.com/docs).
## Installation
```bash
git clone git@github.com:trycourier/courier-csharp.git
dotnet add reference courier-csharp/src/Courier
```
## Requirements
This library requires .NET Standard 2.0 or later.
## Usage
See the [`examples`](examples) directory for complete and runnable examples.
```csharp
using System;
using System.Collections.Generic;
using System.Text.Json;
using Courier;
using Courier.Models;
using Courier.Models.Send;
CourierClient client = new();
SendMessageParams parameters = new()
{
Message = new()
{
To = new UserRecipient() { UserID = "your_user_id" },
Template = "your_template_id",
Data = new Dictionary()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
},
};
var response = await client.Send.Message(parameters);
Console.WriteLine(response);
```
## Client configuration
Configure the client using environment variables:
```csharp
using Courier;
// Configured using the COURIER_API_KEY and COURIER_BASE_URL environment variables
CourierClient client = new();
```
Or manually:
```csharp
using Courier;
CourierClient client = new() { ApiKey = "My API Key" };
```
Or using a combination of the two approaches.
See this table for the available options:
| Property | Environment variable | Required | Default value |
| --------- | -------------------- | -------- | --------------------------- |
| `ApiKey` | `COURIER_API_KEY` | true | - |
| `BaseUrl` | `COURIER_BASE_URL` | true | `"https://api.courier.com"` |
### Modifying configuration
To temporarily use a modified client configuration, while reusing the same connection and thread pools, call `WithOptions` on any client or service:
```csharp
using System;
var response = await client
.WithOptions(options =>
options with
{
BaseUrl = "https://example.com",
Timeout = TimeSpan.FromSeconds(42),
}
)
.Send.Message(parameters);
Console.WriteLine(response);
```
Using a [`with` expression](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) makes it easy to construct the modified options.
The `WithOptions` method does not affect the original client or service.
## Requests and responses
To send a request to the Courier API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a C# class.
For example, `client.Send.Message` should be called with an instance of `SendMessageParams`, and it will return an instance of `Task`.
## Raw responses
The SDK defines methods that deserialize responses into instances of C# classes. However, these methods don't provide access to the response headers, status code, or the raw response body.
To access this data, prefix any HTTP method call on a client or service with `WithRawResponse`:
```csharp
var response = await client.WithRawResponse.Send.Message(parameters);
var statusCode = response.StatusCode;
var headers = response.Headers;
```
The raw `HttpResponseMessage` can also be accessed through the `RawMessage` property.
For non-streaming responses, you can deserialize the response into an instance of a C# class if needed:
```csharp
using System;
using Courier.Models.Send;
var response = await client.WithRawResponse.Send.Message(parameters);
SendMessageResponse deserialized = await response.Deserialize();
Console.WriteLine(deserialized);
```
## Error handling
The SDK throws custom unchecked exception types:
- `CourierApiException`: Base class for API errors. See this table for which exception subclass is thrown for each HTTP status code:
| Status | Exception |
| ------ | -------------------------------------- |
| 400 | `CourierBadRequestException` |
| 401 | `CourierUnauthorizedException` |
| 403 | `CourierForbiddenException` |
| 404 | `CourierNotFoundException` |
| 422 | `CourierUnprocessableEntityException` |
| 429 | `CourierRateLimitException` |
| 5xx | `Courier5xxException` |
| others | `CourierUnexpectedStatusCodeException` |
Additionally, all 4xx errors inherit from `Courier4xxException`.
false
- `CourierIOException`: I/O networking errors.
- `CourierInvalidDataException`: Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response.
- `CourierException`: Base class for all exceptions.
## Network options
### Retries
The SDK automatically retries 2 times by default, with a short exponential backoff between requests.
Only the following error types are retried:
- Connection errors (for example, due to a network connectivity problem)
- 408 Request Timeout
- 409 Conflict
- 429 Rate Limit
- 5xx Internal
The API may also explicitly instruct the SDK to retry or not retry a request.
To set a custom number of retries, configure the client using the `MaxRetries` method:
```csharp
using Courier;
CourierClient client = new() { MaxRetries = 3 };
```
Or configure a single method call using [`WithOptions`](#modifying-configuration):
```csharp
using System;
var response = await client
.WithOptions(options =>
options with { MaxRetries = 3 }
)
.Send.Message(parameters);
Console.WriteLine(response);
```
### Timeouts
Requests time out after 1 minute by default.
To set a custom timeout, configure the client using the `Timeout` option:
```csharp
using System;
using Courier;
CourierClient client = new() { Timeout = TimeSpan.FromSeconds(42) };
```
Or configure a single method call using [`WithOptions`](#modifying-configuration):
```csharp
using System;
var response = await client
.WithOptions(options =>
options with { Timeout = TimeSpan.FromSeconds(42) }
)
.Send.Message(parameters);
Console.WriteLine(response);
```
## Undocumented API functionality
The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.
### Response validation
In rare cases, the API may return a response that doesn't match the expected type. For example, the SDK may expect a property to contain a `string`, but the API could return something else.
By default, the SDK will not throw an exception in this case. It will throw `CourierInvalidDataException` only if you directly access the property.
If you would prefer to check that the response is completely well-typed upfront, then either call `Validate`:
```csharp
var response = client.Send.Message(parameters);
response.Validate();
```
Or configure the client using the `ResponseValidation` option:
```csharp
using Courier;
CourierClient client = new() { ResponseValidation = true };
```
Or configure a single method call using [`WithOptions`](#modifying-configuration):
```csharp
using System;
var response = await client
.WithOptions(options =>
options with { ResponseValidation = true }
)
.Send.Message(parameters);
Console.WriteLine(response);
```
## Semantic versioning
This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
2. Changes that we do not expect to impact the vast majority of users in practice.
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
We are keen for your feedback; please open an [issue](https://www.github.com/trycourier/courier-csharp/issues) with questions, bugs, or suggestions.