Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4daa48e
Refresh dotnet/python/typescript skills for adyen (0.2.1 -> 0.3.0)
alifsayalee Oct 12, 2026
856d260
Refresh dotnet/python/typescript skills for alpaca (0.2.2 -> 0.3.0)
alifsayalee Oct 12, 2026
d03b318
Refresh dotnet/python/typescript skills for binance (0.2.2 -> 0.3.0)
alifsayalee Oct 12, 2026
cd33c46
Refresh dotnet/python/typescript skills for coingecko (0.2.2 -> 0.3.0)
alifsayalee Oct 12, 2026
95bb67d
Refresh dotnet/python/typescript skills for deepgram (0.2.1 -> 0.3.0)
alifsayalee Oct 12, 2026
1d545ea
Refresh dotnet/python/typescript skills for discourse (0.2.1 -> 0.3.0)
alifsayalee Oct 12, 2026
56a1dc7
Refresh dotnet/python/typescript skills for finnhub (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
65d48e5
Refresh dotnet/python/typescript skills for firecrawl (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
49abe34
Refresh dotnet/python/typescript skills for frankfurter (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
f2418c2
Refresh dotnet/python/typescript skills for google-maps (0.1.2 -> 0.2.0)
alifsayalee Oct 12, 2026
1d19881
Refresh dotnet/python/typescript skills for maxio (0.2.2 -> 0.3.0)
alifsayalee Oct 12, 2026
02f5157
Refresh dotnet/python/typescript skills for notion (0.1.2 -> 0.2.0)
alifsayalee Oct 12, 2026
a29c2b6
Refresh dotnet/python/typescript skills for nytimes (0.1.2 -> 0.2.0)
alifsayalee Oct 12, 2026
a31abe8
Refresh dotnet/python/typescript skills for paypal (0.3.3 -> 0.4.0)
alifsayalee Oct 12, 2026
a3e333f
Refresh dotnet/python/typescript skills for plaid (0.1.2 -> 0.2.0)
alifsayalee Oct 12, 2026
49e535f
Refresh dotnet/python/typescript skills for shutterstock (0.3.4 -> 0.…
alifsayalee Oct 12, 2026
8294ba4
Refresh dotnet/python/typescript skills for slack (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
471e399
Refresh dotnet/python/typescript skills for sportsdata (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
88701de
Refresh dotnet/python/typescript skills for spotify (0.1.2 -> 0.2.0)
alifsayalee Oct 12, 2026
cf5b6f4
Refresh dotnet/python/typescript skills for square (0.3.1 -> 0.4.0)
alifsayalee Oct 12, 2026
3a4ac37
Refresh dotnet/python/typescript skills for tesla (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
9907c5b
Refresh dotnet/python/typescript skills for twilio (0.3.4 -> 0.4.0)
alifsayalee Oct 12, 2026
1bc52b8
Refresh dotnet/python/typescript skills for verizon (0.2.1 -> 0.3.0)
alifsayalee Oct 12, 2026
45c6779
Refresh dotnet/python/typescript skills for vimeo (0.2.3 -> 0.3.0)
alifsayalee Oct 12, 2026
5677b7e
Sync marketplace registries and docs
alifsayalee Oct 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Each supported language ships the same eight:
The `getting-started` skill is the entry point: it directs the agent to clone and grep the real SDK
source, so every fact is grounded in the actual contract rather than model knowledge.

Across the marketplace that's **<!-- BEGIN:LANGUAGE_PACK_COUNT -->72<!-- END:LANGUAGE_PACK_COUNT --> language packs and <!-- BEGIN:SKILL_COUNT -->648<!-- END:SKILL_COUNT --> skills**. See
Across the marketplace that's **<!-- BEGIN:LANGUAGE_PACK_COUNT -->72<!-- END:LANGUAGE_PACK_COUNT --> language packs and <!-- BEGIN:SKILL_COUNT -->696<!-- END:SKILL_COUNT --> skills**. See
[`plugins/paypal/README.md`](plugins/paypal/README.md) for a worked example.

## Repository structure
Expand Down
2 changes: 1 addition & 1 deletion plugins/adyen/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adyen",
"displayName": "Adyen",
"version": "0.2.1",
"version": "0.3.0",
"description": "Integrate and consume the APIMatic-generated Adyen SDK — bundled skills for C#/.NET, python, TypeScript.",
"author": {
"name": "APIMatic",
Expand Down
2 changes: 1 addition & 1 deletion plugins/adyen/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adyen",
"displayName": "Adyen",
"version": "0.2.1",
"version": "0.3.0",
"description": "Integrate and consume the APIMatic-generated Adyen SDK — bundled skills for C#/.NET, python, TypeScript.",
"author": {
"name": "APIMatic",
Expand Down
2 changes: 1 addition & 1 deletion plugins/adyen/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adyen",
"displayName": "Adyen",
"version": "0.2.1",
"version": "0.3.0",
"description": "Integrate and consume the APIMatic-generated Adyen SDK — bundled skills for C#/.NET, python, TypeScript.",
"author": {
"name": "APIMatic",
Expand Down
237 changes: 48 additions & 189 deletions plugins/adyen/skills/dotnet/dotnet-authentication/SKILL.md

Large diffs are not rendered by default.

171 changes: 103 additions & 68 deletions plugins/adyen/skills/dotnet/dotnet-calling-endpoints/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,76 +16,98 @@ names follow no fixed verb/resource pattern, so take the real name from the shee

## Method signature convention

Every endpoint method is `async` (returns a `Task`) and lays its parameters out in a fixed order:
Every endpoint method is `async` (returns a `Task`) and takes at most three parameters, in a fixed order:

```csharp
public Task<{ReturnType}> {Operation}(
{non-defaulted params}, // no C# default value — listed first
{defaulted params} = {default}, // have a C# default (e.g. = null, = 1d) — may be skipped
RequestOptions? requestOptions = null, // on EVERY operation — see below
CancellationToken ct = default); // always last
{Operation}Request request, // every input — absent when the operation takes none
RequestOptions? requestOptions = null, // on EVERY operation — see below
CancellationToken cancellationToken = default); // always last
```

- **Parameter order is fixed:** parameters **without a default value come first**, then parameters **with a
default value**, then `RequestOptions? requestOptions = null`, then `CancellationToken ct = default` last
(C# requires defaulted parameters to follow non-defaulted ones).
- **`requestOptions` is on every generated operation**, between the last defaulted parameter and `ct`. It
- **Every input travels on one request record.** Path, query and header parameters, the body, and the
fields of a form all become properties of `{Operation}Request`. There are no flat arguments, so there is
no parameter order to get wrong: you build the record with an object initializer and set members by name.
- **`request` has no default.** An operation that takes input always needs a record, even when every member
is optional — pass `new {Operation}Request()`. An operation that takes **no** input has no `request`
parameter at all.
- **The record lives in `Requests/`**, in the namespace `{RootNamespace}.Requests` for an operation on the
client and `{RootNamespace}.Requests.{ApiGroup}` for one on a controller. An operation with several
tags is filed under the first tag it declares, so its namespace can name a different controller from
the one you call it through. Its name is normally `{Operation}Request`; where a model already owns that
name it is `{Operation}OperationRequest`. Take the real name and file from the operation's
**Type sources** table — never assume it.
- **`requestOptions` is on every generated operation**, between `request` and `cancellationToken`. It
is a `{RootNamespace}.Core.RequestOptions` with two properties — `LogLevel?`, a per-call logging
override, and `Hooks`, a per-call `SdkHook` list appended after the client-wide `options.Hooks`
(both in **dotnet-configuration-resilience**). You will rarely set it, but you must **count** it: a
positional call written from a signature that leaves it out puts your `CancellationToken` where a
`RequestOptions?` is expected, and the call fails to compile with
`CS1503: Argument N: cannot convert from 'System.Threading.CancellationToken' to
'{RootNamespace}.Core.RequestOptions?'`. Pass `ct:` by name and the problem cannot arise.
- **An optional parameter may still have no C# default.** Many nullable query params are generated without a
`= null` default (e.g. `string? startDate`), so they sit in the leading group and must be passed
explicitly (as `null`) in a positional call — which is why named arguments matter (see below).
- **The contract sheet is the source of truth for the signature.** Whether a parameter is nullable,
required, or defaulted — and whether the operation takes a body — varies per operation. Path params are
typically non-nullable primitives listed first; query and body params may be required or optional. Take
each operation's exact signature from the contract sheet (grounded from the SDK map/source), not from memory.
positional call that skips it puts your `CancellationToken` where a `RequestOptions?` is expected, and the
call fails to compile with `CS1503: Argument N: cannot convert from 'System.Threading.CancellationToken'
to '{RootNamespace}.Core.RequestOptions?'`. Pass `cancellationToken:` by name and the problem cannot arise.
- **The contract sheet is the source of truth for the record.** Which members are `required`, which are
nullable, which carry a default — and whether there is a `Body` — varies per operation. Take each
operation's record from the contract sheet (grounded from the SDK map/source), not from memory.
- **Return type** varies by operation — see [Reading the response](#making-the-call-and-reading-the-response).
- Methods are **async-only** (no sync overloads) and **throw `SdkException<TError>`** on API errors — see
- Methods are **async-only** (no sync overloads) and **throw `ApiException<TError>`** on API errors — one leaf
of the SDK's `SdkException` family, which also covers connection failures and timeouts — see
`dotnet-error-handling`.

## Use named arguments for list/search endpoints
## Building the request record

List/search operations can have **many** optional parameters in a **fixed positional order**, and many of
the leading nullable ones have **no default value** — so you cannot skip them positionally.
The record's source file is the parameter list. Each property is one of four shapes, and the shape tells you
what you owe it:

Call these methods with named arguments. A positional call reconstructed from memory or an incomplete view
of the signature mis-binds arguments (wrong order, or a missing non-defaulted arg before the first defaulted
one), so it either fails to compile or sends the wrong request; named arguments are order-independent and
avoid this. When copying:

- Copy parameter names and order from the C# method signature (`public Task<...> {Operation}(...)`), not
from the internal `new Param("...", ...)` builder list inside the method body — that list is ordered
differently and uses snake_case wire names.
- Copy each name verbatim from the signature; they are easy to misremember (singular vs plural, etc.).
| Property | Meaning | You |
|---|---|---|
| `public required T X { get; init; }` | required, no spec default | **must** set it — the compiler enforces this |
| `public T X { get; init; } = value;` | the spec declares a default | set it only to override; leaving it sends the default |
| `public T? X { get; init; }` | optional, no default | leave it unset to omit it from the request |
| `public T X { get; } = value;` | the spec fixes the value (`const`) | cannot set it — it is sent as declared |

```csharp
// Named args: order-independent; omitted optionals fall through to null / their defaults.
var response = await client.{ApiGroup}.{Operation}(
status: {EnumType}.SomeConstant,
someFilterId: 12345d,
someFlag: true,
page: 1, // int? or double? per API — take the type from the contract sheet
perPage: 100,
ct: ct);
new {Operation}Request
{
Status = {EnumType}.SomeConstant,
SomeFilterId = 12345d,
Page = 1, // int or double per API — take the type from the record
PerPage = 100
},
cancellationToken: ct);
```

- **Property names are PascalCase C# names, not wire names.** `per_page` on the wire is `PerPage` on the
record. The wire keys appear only inside the generated method body, as `new Param("per_page", request.PerPage)`
— read names off the record, never off that list.
- **The record is never serialized**, so it carries no `[JsonPropertyName]`. Its members may carry constraint
attributes (`[Minimum(0)]`, `[MaxLength(256)]`); they document the API's limits and nothing in the SDK
enforces them before the call.
- **A JSON, plain-text or binary body is always the member `Body`** (`Body_` in the rare API that also has a parameter
literally named `body`). A `application/x-www-form-urlencoded` or multipart form has **no** `Body`: each
form field is its own property on the record, and the generator assembles the form itself.

## Files

A file is a `BinaryContent`, built with an object initializer that sets all three: a `Stream`, a `FileName`
(may be `null`) and a `ContentType`
(a `MediaTypeHeaderValue`). A `Stream` or `byte[]` also converts to one, typed `application/octet-stream` and
named only for a `FileStream`; the SDK does not apply the spec's media type, so set `ContentType` whenever the spec
declares one, and `FileName` when the API needs a name. The SDK never disposes or rewinds your stream, and never retries a call
that sends a file.

## Building request models

**Only a JSON-bodied operation has a `body` parameter.** Where the API declares a
`application/x-www-form-urlencoded` request, the generator emits the fields as *individual method
parameters* and assembles the form itself — there is no request record to construct and no `body` argument
to pass. In an API built that way this is the majority shape, not an exception. The contract sheet says
which you are looking at; the signature settles it.
**A form-bodied operation has no `Body` member.** Where the API declares a
`application/x-www-form-urlencoded` or multipart request, the generator emits the fields as *individual
members of the request record* and assembles the form itself — there is no body model to construct and no
`Body` to set.
In an API built that way this is the majority shape, not an exception. The contract sheet says
which you are looking at; the record settles it.

For the JSON case: request bodies are immutable `record`s built with object-initializer syntax (no
builders). `required` members must be set; optional ones are nullable and are omitted from the JSON when
left null. The request type is the type of the operation's `body` parameter — take its exact name from the
contract sheet (grounded from the SDK map/source):
left null. The body model is the type of the request record's `Body` member — a different type from the
request record itself — so take its exact name from the contract sheet (grounded from the SDK map/source):

```csharp
var body = new {RequestType}
Expand All @@ -112,14 +134,15 @@ var body = new {RequestType}

## Enums

Enums are type-safe string- **or int-**enums (`StringEnum<T>` / `IntEnum<T>`), not C# enums — use the
static constants, or `FromValue(...)` for a value not known at compile time — where the enum exposes it;
some do not, and `dotnet-models` says which to check. See **dotnet-models** for
read-back semantics (they convert to their underlying value; `==` compares by value; guard unknowns).
Enums are type-safe string- **or int-**enums (`OpenStringEnum<T>` / `OpenIntEnum<T>`), not C# enums — use
the static constants. There is no `FromValue`: a value the spec does not declare cannot be constructed, and
a raw value resolves through `{EnumType}.TryGetKnownValue(value, out var known)`. See **dotnet-models** for
read-back semantics (implicit conversion to the underlying value, `==` / `Is` against raw values, and the
generated `Match`).

```csharp
SomeProp = {EnumType}.SomeConstant;
SomeProp = {EnumType}.FromValue("server_provided_value");
SomeProp = {EnumType}.TryGetKnownValue(configured, out var known) ? known : {EnumType}.SomeConstant;
```

## Union types, collections, and dates
Expand All @@ -132,11 +155,13 @@ how to construct and read it.
## Making the call and reading the response

```csharp
var response = await client.{ApiGroup}.{Operation}(pathArg, queryArg: null, body: body, ct: ct);
var response = await client.{ApiGroup}.{Operation}(
new {Operation}Request { {PathMember} = pathValue, Body = body },
cancellationToken: ct);
```

> **Wrap the call in error handling — a non-2xx response *throws*, it is not signalled by the return value.**
> The bare `await` above shows only the happy path; on an API error the call throws `SdkException<TError>`.
> The bare `await` above shows only the happy path; on an API error the call throws `ApiException<TError>`.
> Before writing a real call, **load `dotnet-error-handling`** for how to wrap it — the `try/catch` shape and
> which `TError` to catch per operation — or use the non-throwing `{Operation}Result` variant (below).

Expand All @@ -151,13 +176,18 @@ contract sheet's response-envelope column names the return type and the inner fi
```
- **The resource directly** — `Task<{Resource}>`: use it as-is, nothing to unwrap.
```csharp
var resource = await client.{ApiGroup}.{Operation}(...);
var resource = await client.{ApiGroup}.{Operation}(request, cancellationToken: ct);
```
- **An array** — `Task<IReadOnlyList<{ItemType}>>`: iterate it, unwrapping each item too if the items are
themselves nesting objects.
- **An object that nests an array** — a record whose single member is an `IReadOnlyList<...>`. Read that
member first, then iterate.
- **Nothing** — non-generic `Task`: no body; just `await` it.
- **A file** — `Task<BinaryContent>`: the call returns when the headers arrive, and the body is still on the
open connection. Dispose it to free the connection, even if you never read it. `FileName` comes from the
server's `Content-Disposition` and may be null, so sanitize it before you use it as a path. No SDK timeout
bounds the read, and a drop while you read throws a raw `IOException` from your read, not
`SdkConnectionException`.

Endpoints in the same family can differ — one nests the resource, another returns it directly — so let each
method's return type guide how you read it.
Expand All @@ -169,27 +199,32 @@ exist. See **dotnet-error-handling**.

## Cancellation

Every operation takes a `CancellationToken` as its last argument, passed as `ct:`, with
`RequestOptions? requestOptions = null` immediately before it — so `ct` is last, never second-to-last. To bound an individual call with a
Every operation takes a `CancellationToken` as its last argument, passed as `cancellationToken:`, with
`RequestOptions? requestOptions = null` immediately before it — so the token is last, never second-to-last. To bound an individual call with a
timeout, use the per-request cancellation pattern in **dotnet-configuration-resilience** (it owns
timeouts).

## Worked example — a list/GET call

```csharp
// Signature (illustrative):
// Task<IReadOnlyList<{ItemType}>> {Operation}(
// {EnumType}? filter, string? startDate, string? q,
// {Num}? page = {p}, {Num}? perPage = {n}, // {Num} is int? or double? PER API — check the sheet
// RequestOptions? requestOptions = null, CancellationToken ct = default);
// Record (illustrative) — Requests/{ApiGroup}/{Operation}Request.cs:
// public sealed record {Operation}Request
// {
// public {EnumType}? Filter { get; init; }
// public string? StartDate { get; init; }
// public string? Q { get; init; }
// public {Num} Page { get; init; } = {p}; // {Num} is int or double PER API — check the record
// public {Num} PerPage { get; init; } = {n};
// }

var results = await client.{ApiGroup}.{Operation}(
filter: {EnumType}.SomeConstant,
startDate: null,
q: "search text",
page: 1, // literal must match the parameter's type — a `1d` against an `int?` is CS1503
perPage: 20,
ct: ct);
new {Operation}Request
{
Filter = {EnumType}.SomeConstant,
Q = "search text",
PerPage = 20 // literal must match the member's type — a `20d` against an `int` is CS0266
}, // StartDate is left unset and omitted; Page keeps the spec default
cancellationToken: ct);

foreach (var item in results)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public {Api}Client(HttpClient httpClient, {Api}ClientOptions options)

Operations are exposed on the client. Most are grouped under **controller properties** (one per API resource
group) and called `client.{ApiGroup}.{Operation}(...)` — for example, a `Widgets` controller's
`ListWidgets` operation is `client.Widgets.ListWidgets(...)`. An operation that belongs to no group sits
`ListWidgets` operation is `client.Widgets.ListWidgets(new ListWidgetsRequest { ... })`. An operation that belongs to no group sits
**directly on the client**, called `client.{Operation}(...)`. The available controller properties (and any
direct operations) come from the contract sheet (grounded from the SDK map/source),
not a decompiled or reflected view of the installed package. See `dotnet-calling-endpoints`.
Expand Down
Loading
Loading