---
title: Basic methods
llmstxt: true
---

import { ClientTabs, ClientTabItem } from "@components/client-tabs";

This page documents the default generation logic for client's basic method as well as how to customize it.
For advanced paging, long-running, multipart or streaming operations, see the [Paging Operations](../05pagingoperations/), [Long-Running Operations](../06longrunningoperations/), [Multipart Operations](../07multipart/) and [Streaming Operations](../13streaming/) pages.

## Convenience and protocol methods

### Default behaviors

By default, any language code generator will generate both protocol methods and convenient methods for an operation.

> **NOTE:** Python and Typescript don't have a separation of convenient/protocol methods.

<ClientTabs>

```typespec title=main.tsp
namespace PetStoreNamespace;

/** This is the input I need */
@resource("output")
model OutputModel {
  /** Id of this object */
  @key
  @visibility(Lifecycle.Read)
  name: string;
}

/** Read my resource */
op GetModel is ResourceRead<OutputModel>;
```

```python
class OutputModel:
  name: str = rest_field(readonly=True)
response: OutputModel = client.get(name="name")
```

```csharp
namespace PetStoreNamespace.Models
{
  public partial class OutputModel
  {
    public string Name { get; }
  }
}

namespace PetStoreNamespace
{
  public partial class PetStoreNamespaceClient
  {
    // protocol method
    public virtual async Task<Response> GetModelAsync(string name, RequestContext context) {}
    public virtual Response GetModel(string name, RequestContext context) {}
    // convenience method
    public virtual async Task<Response<OutputModel>> GetModelAsync(string name, CancellationToken cancellationToken = default) {}
    public virtual Response<OutputModel> GetModel(string name, CancellationToken cancellationToken = default) {}
  }
}
```

```typescript
interface OutputModel {
  name: string;
}

const model: OutputModel = await client.path("/petStore/model/{name}").get();
```

```java
package petstorenamespace.models;
public final class OutputModel {
    public String getName()
}

package petstorenamespace;
public final class PetStoreNamespaceClient {
    // protocol method
    public Response<BinaryData> getModelWithResponse(String name, RequestOptions requestOptions)
    // convenient method
    public OutputModel getModel(String name)
}
```

```go
type OutputModel struct {
  Name string `json:"name"`
}

type PetStoreNamespaceClient struct {}

type PetStoreNamespaceClientGetModelOptions struct {}

type PetStoreNamespaceClientGetModelResponse struct {
	OutputModel
}

func (client *PetStoreNamespaceClient) GetModel(ctx context.Context, name string, options *PetStoreNamespaceClientGetModelOptions) (PetStoreNamespaceClientGetModelResponse, error)

```

</ClientTabs>

### Customizations

The detailed generation configuration of protocol and/or convenient methods that can be done:

As emitters global parameters:

- `generate-protocol-methods`: boolean flag to shift the entire generation for the process (`true` by default)
- `generate-convenience-methods`: boolean flag to shift the entire generation for the process (`true` by default)

To set global emitters parameters, read the documentation of [emitters configuration](https://microsoft.github.io/typespec/introduction/configuration#configuration-file).

For fine tuning, the set of decorators `@protocolAPI` and `@convenientAPI` can be used. They take a required boolean as parameter.

#### Shifting the generation of protocol and convenience on and off

This can be achieved with the augment operator and the emitter package

<ClientTabs>

```typespec title=client.tsp
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

@@convenientAPI(PetStoreNamespace.GetModel, false);
```

```python
# Python do not change behavior based on protocolAPI or convenientAPI
```

```csharp
// Model class is not generated.
// Convenient method is not generated.

namespace PetStoreNamespace
{
  public partial class PetStoreNamespaceClient
  {
    // protocol method
    public virtual async Task<Response> GetModelAsync(string name, RequestContext context) {}
    public virtual Response GetModel(string name, RequestContext context) {}
  }
}
```

```typescript
// Typescript do not change behavior based on protocolAPI or convenientAPI
```

```java
// Model class is not generated.
// Convenient method is not generated.

public final class PetStoreNamespaceClient {
    // protocol method
    public Response<BinaryData> getModelWithResponse(String name, RequestOptions requestOptions)
}
```

```go
// NOT_SUPPORTED
```

</ClientTabs>

#### Make methods private/internal

Sometimes it may be useful to still generate the method, but to make it private, so it can be re-used by a manual code wrapper.

The two possible value for the `Access` enum are `internal` and `public`.

<ClientTabs>

```typespec title=client.tsp
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

@@access(PetStoreNamespace.GetModel, "internal");
```

```python
# can't import form models directly
from petstorenamespace.models import GetModel # will report error
```

```csharp
// Model class is internal
namespace PetStoreNamespace.Models
{
  internal partial class OutputModel
  {
    public string Name { get; }
  }
}
// Client method is internal
namespace PetStoreNamespace
{
  public partial class PetStoreNamespaceClient
  {
    //protocol method
    internal virtual async Task<Response> GetModelAsync(string name, RequestContext context) {}
    internal virtual Response GetModel(string name, RequestContext context) {}
    //convenience method
    internal virtual async Task<Response<OutputModel>> GetModelAsync(string name, CancellationToken cancellationToken = default) {}
    internal virtual Response<OutputModel> GetModel(string name, CancellationToken cancellationToken = default) {}
  }
}
```

```typescript
// Typescript do not change behavior based on protocolAPI or convenientAPI
```

```java
// Model class resides in implementation package.
// Client method is package private.

package petstorenamespace.implementation.models;
public final class OutputModel {
    public String getName()
}

package petstorenamespace;
public final class PetStoreNamespaceClient {
    // protocol method
    Response<BinaryData> getModelWithResponse(String name, RequestOptions requestOptions)
    // convenient method
    OutputModel getModel(String name)
}
```

```go
// Go generates the model and method as `outputModel` / `getModel` (unexported),
// so they are not part of the package's public API.
type outputModel struct {
    // READ-ONLY
    Name *string
}

func (client *PetStoreNamespaceClient) getModel(ctx context.Context, apiVersion string, name string, options *petStoreNamespaceClientgetModelOptions) (petStoreNamespaceClientgetModelResponse, error)
```

</ClientTabs>

#### Decide the usage of a model

Models can be used for input, output, or both at the same time. In some languages, this
changes the way the API is exposed for those models.

By default, the code generator will infer the usage based on the TypeSpec. If this inference doesn't
correspond to expectation, this can be customized with the `usage` decorator.

Possible values are:

- `Usage.input`: type is used in request payloads.
- `Usage.output`: type is used in response payloads.
- `Usage.json`: type is used in JSON payloads.
- `Usage.xml`: type is used in XML payloads.

Values can be combined with bitwise OR (`|`) to express all applicable contexts. For example,
`Usage.input | Usage.output | Usage.json` means the type is round-trip (both request and response)
and JSON-based.

The `@usage` decorator can be applied to individual models, enums, or unions. It can also be applied to a **namespace**, in which case the usage propagates recursively to all models, enums, and unions defined within that namespace and its nested sub-namespaces. This includes types in imported libraries when using augment decorators (`@@usage`).

> **NOTE:** If a model is never used, it will not be generated. Assigning a usage will force generation.

<ClientTabs>

```typespec title=client.tsp
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

// This model is input only
@@usage(Azure.OpenAI.AzureCognitiveSearchIndexFieldMappingOptions, Usage.input);
// This models is input/output
@@usage(Azure.OpenAI.ImageGenerations, Usage.input | Usage.output);
```

```python
# Python doesn't generate different code based on usage
# However, the model may not be generated if it's never used
# In that case, set a usage for the model
```

```csharp
// If a model is input-only, it has one public constructor with all required properties as parameters.
// The required properties only have getter. Optional properties have both getter and setter.
// A collection property which is not nullable only has getter whatever it is required or not.
namespace Azure.AI.OpenAI.Models
{
  public partial class AzureCognitiveSearchIndexFieldMappingOptions
  {
    public AzureCognitiveSearchIndexFieldMappingOptions()

    public string TitleFieldName { get; set; }
    public string UrlFieldName { get; set; }
    public string FilepathFieldName { get; set; }
    public IList<string> ContentFieldNames { get; }
    public string ContentFieldSeparator { get; set; }
    public IList<string> VectorFieldNames { get; }
    public IList<string> ImageVectorFieldNames { get; }
  }
}
// If a model is output-only, it does not have any public constructor, and all properties only have getter, no setter.

// If a model is roundtrip (input + output), it has one public constructor with all required properties as parameters.
// All properties except colletion properties which are not nullable will have both getter and setter.
// A collection property which is not nullable only has getter.
namespace Azure.AI.OpenAI.Models
{
  public partial class ImageGenerations
  {
    public ImageGenerations(DateTimeOffset created, IEnumerable<ImageGenerationData> data)

    public DateTimeOffset Created { get; set; }
    public IList<ImageGenerationData> Data { get; }
  }
}
```

```typescript
// JS doesn't generate different code based on usage
// However, the model may not be generated if it's never used
// In that case, set a usage for the model
```

```java
// If a model class is output-only, its constructor is not public.
// Adding Usage.input to it would make its constructor public.

package azure.openai.models;

public final class AzureCognitiveSearchIndexFieldMappingOptions {
    public AzureCognitiveSearchIndexFieldMappingOptions()
    public String getTitleField()
    public AzureCognitiveSearchIndexFieldMappingOptions setTitleField(String titleField)
    ...
}

public final class ImageGenerations {
    public ImageGenerations(OffsetDateTime createdAt, List<ImageGenerationData> data)
    public OffsetDateTime getCreatedAt()
    public List<ImageGenerationData> getData()
}
```

```go
// Go does not generate different code based on usage.
// However, the model may not be generated if it's never used.
// In that case, set a usage for the model.
```

</ClientTabs>

## Basic method signature

### Simple methods

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
model User {
  firstName: string;
  lastName: string;
}

@get
op get(): User;

@post
op post(@body body: User): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >

```python
def get() -> User:
  ...

@overload
def post(body: User, **kwargs: Any) -> None:
  ...

@overload
def post(body: JSON, **kwargs: Any) -> None:
  ...

@overload
def post(body: IO[bytes], **kwargs: Any) -> None:
  ...

def post(body: [User, JSON, IO[bytes]], **kwargs: Any) -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
//protocol method
public virtual async Task<Response> GetUserAsync(RequestContext context){}
public virtual Response GetUser(RequestContext context){}
//convenience method
public virtual async Task<Response<User>> GetUser(CancellationToken cancellationToken = default)
public virtual Response<User> GetUser(CancellationToken cancellationToken = default)

//protocol method
public virtual async Task<Response> PostAsync(RequestContent content, RequestContext context = null)
public virtual Response Post(RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> PostAsync(User user, CancellationToken cancellationToken = default)
public virtual Response Post(User user, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Api Layer
export async function get(): Promise<User>;
export async function post(body: User, options: PostOptionalParams): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  get(options: GetUserOptionalParams): Promise<User>;
  post(body: User, options: PostOptionalParams): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public User get();
public void post(User user);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientGetOptions struct {}

type ClientPostOptions struct {}

type ClientGetResponse struct {
	User
}

type ClientPostResponse struct {}

func (client *Client) Get(ctx context.Context, options *ClientGetOptions) (ClientGetResponse, error)

func (client *Client) Post(ctx context.Context, body User, options *ClientPostOptions) (ClientPostResponse, error)
```

</ClientTabItem>
</ClientTabs>

### Spread cases

Please exercise caution when using the _spread_ feature.

- The model to be spread should have fewer than 6 settable properties. See [simple methods](https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-parameters).
- The model to be spread should remain stable across api-versions. Adding an optional property across api-versions could result in one additional method overload in SDK client.
- The model to be spread should not be used in [JSON Merge Patch](https://datatracker.ietf.org/doc/html/rfc7386).

#### Alias

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
alias User = {
  firstName: string;
  lastName: string;
};

@post
op upload(...User): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >

For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
def upload(first_name: str, last_name: str) -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
//protocol method
public virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)
public virtual Response Upload(RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> UploadAsync(string firstName, string lastName, CancellationToken cancellationToken = default)
public virtual Response Upload(string firstName, string lastName, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Api Layer
export async function upload(
  firstName: string,
  lastName: string,
  options: UploadOptionalParams,
): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  upload(firstName: string, lastName: string, options: UploadOptionalParams): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public void upload(String firstName, String lastName);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientUploadOptions struct {}

type ClientUploadResponse struct {}

func (client *Client) Upload(ctx context.Context, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Alias with @header/@query/@path properties

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
alias User = {
  @path id: string;
  firstName: string;
  lastName: string;
};

op upload(...User): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >

For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
def upload(self, id: str, first_name: str, last_name: str, *, content_type: str = "application/json") -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
//protocol method
public virtual async Task<Response> UploadAsync(string id, RequestContent content, RequestContext context = null)
public virtual Response Upload(string id, RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> UploadAsync(string id, string firstName, string lastName, CancellationToken cancellationToken = default)
public virtual Response Upload(string id, string firstName, string lastName, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Api Layer
export async function upload(
  id: string,
  firstName: string,
  lastName: string,
  options: UploadOptionalParams,
): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  upload(
    id: string,
    firstName: string,
    lastName: string,
    options: UploadOptionalParams,
  ): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public void upload(String id, String firstName, String lastName);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientUploadOptions struct {}

type ClientUploadResponse struct {}

func (client *Client) Upload(ctx context.Context, id string, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Named model

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
model User {
  firstName: string;
  lastName: string;
}

op upload(...User): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
def upload(self, first_name: str, last_name: str, *, content_type: str = "application/json") -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
public partial class User
{
  public User(string firstName, string lastName) { }
  public string FirstName { get; }
  public string LastName { get; }
}
//protocol method
public virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)
public virtual Response Upload(RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> UploadAsync(User user, CancellationToken cancellationToken = default)
public virtual Response Upload(string firstName, string lastName, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Api Layer
export async function upload(
  firstName: string,
  lastName: string,
  options: UploadOptionalParams,
): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  upload(firstName: string, lastName: string, options: UploadOptionalParams): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public void upload(String firstName, String lastName);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientUploadResponse struct {}

type ClientUploadOptions struct {}

func (client *Client) Upload(ctx context.Context, firstName string, lastName string, options *ClientUploadOptions) (ClientUploadResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Model with `@body` property

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
model User {
  firstName: string;
  lastName: string;
}

model UserRequest {
  @body user: User;
}

op upload(...UserRequest): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >

For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
def upload(self, body: [User, JSON, IO[bytes]], *, content_type: str = "application/json") -> None:
  ...
```

</ClientTabItem>

<ClientTabItem lang="csharp" >

```csharp
public partial class User
{
  public User(string firstName, string lastName){}
  public string FirstName { get; }
  public string LastName { get; }
}
//protocol method
public virtual async Task<Response> UploadAsync(RequestContent content, RequestContext context = null)
public virtual Response Upload(RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> UploadAsync(User user, CancellationToken cancellationToken = default)
public virtual Response Upload(User user, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Api Layer
export async function upload(user: User, options: UploadOptionalParams): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  upload(user: User, options: UploadOptionalParams): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
// Model class
@Immutable
public final class User implements JsonSerializable<User> {
    public User(String firstName, String lastName);
    public String getFirstName();
    public String getLastName();
}

// Client API
public void upload(User user);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type User struct {
  FirstName *string
  LastName *string
}

type ClientUploadOptions struct {}

type ClientUploadResponse struct {}

func (client *Client) Upload(ctx context.Context, user User, options *ClientUploadOptions) (ClientUploadResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Model with @header/@query/@path properties

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
model BlobProperties {
  @path
  name: string;

  @header
  testHeader: string;
}

@route("blob_properties/{name}")
op getBlobProperties(...BlobProperties): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python

def get_blob_properties(self, name: str, *, test_header: string, content_type: str = "application/json") -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
//protocol method
public virtual async Task<Response> GetBlobPropertiesAsync(string name, string testHeader, RequestContext context = null)
public virtual Response GetBlobProperties(string name, string testHeader, RequestContext context = null)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen Options
export interface GetBlobPropertiesOptionalParams extends OperationOptions {
  requestOptions: {
    headers: {
      test-header: string
    } & RawHttpHeadersInput
  }
}

// JS CodeGen api layer
export async function getBlobProperties(name: string, options: GetBlobPropertiesOptionalParams): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  getBlobProperties(name: string, options: GetBlobPropertiesOptionalParams): Promise<void>
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public void getBlobProperties(String name, String testHeader);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientGetBlobPropertiesOptions struct {
}

type ClientGetBlobPropertiesResponse struct {
}

func (client *Client) GetBlobProperties(ctx context.Context, name string, testHeader string, options *ClientGetBlobPropertiesOptions) (ClientGetBlobPropertiesResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Model mixed with normal and @header/@query/@path properties

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
model Schema {
  @header contentType: "application/json";
  schema: bytes;
}

@post
op register(...Schema): void;
```

</ClientTabItem>

<ClientTabItem lang="python" >
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
class Schema:
  schema: bytes

def register(self, body: [Schema, JSON, IO[bytes]], *, content_type: str = "application/json") -> None:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp
public partial class Schema
{
  public Schema(BinaryData schemaProperty){}
  public BinaryData SchemaProperty { get; }
}
//protocol method
public virtual async Task<Response> RegisterAsync(RequestContent content, RequestContext context = null)
public virtual Response Register(RequestContent content, RequestContext context = null)
//convenience method
public virtual async Task<Response> RegisterAsync(Schema schema, CancellationToken cancellationToken = default)
public virtual Response Register(Schema schema, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen model
export interface Schema {
  schema: string;
}

// JS CodeGen api layer
export async function register(
  body: Schema,
  options: GetBlobPropertiesOptionalParams,
): Promise<void>;

// JS CodeGen classical client layer
export class DemoServiceClient {
  getBlobProperties(body: Schema, options: GetBlobPropertiesOptionalParams): Promise<void>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
// Model class
@Immutable
public final class Schema implements JsonSerializable<Schema> {
    public Schema(byte[] schema);
    public byte[] getSchema();
}

// Client API
public void register(Schema schema);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type ClientRegisterResponse struct {}

type ClientRegisterOptions struct {}

func (client *Client) Register(ctx context.Context, schema []byte, options *ClientRegisterOptions) (ClientRegisterResponse, error)

```

</ClientTabItem>
</ClientTabs>

#### Using Azure.Core.ResourceOperations template

Resource create and update operations are not impacted by spread since they all have explicit defined body parameter.
Only resource action operations are impacted by spread.

If the action parameter is a model, then the model will be spread.

<ClientTabs>
<ClientTabItem lang="typespec" >

```typespec
@resource("widgets")
model Widget {
  @key("widgetName")
  name: string;
}

model RepairInfo {
  problem: string;
  contact: string;
}

model RepairResult {
  reason: string;
  info: string;
}

alias Operations = Azure.Core.ResourceOperations<{}>;

op scheduleRepairs is Operations.ResourceAction<Widget, RepairInfo, RepairResult>;
```

</ClientTabItem>

<ClientTabItem lang="python" >
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
class RepairInfo:
  problem: str
  contact: str

class RepairResult:
  reason: str
  info: str

def scheduleRepairs(self, widget_name: str, problem: str, contact: str, *, content_type: str = "application/json") -> RepairResult:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp

```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen api layer
export async function scheduleRepairs(
  context: Client,
  widgetName: string,
  problem: string,
  contact: string,
  options: ScheduleRepairsOptionalParams = { requestOptions: {} },
): Promise<RepairResult>;

// JS CodeGen classical client layer
export class WidgetServiceClient {
  scheduleRepairs(
    widgetName: string,
    problem: string,
    contact: string,
    options: ScheduleRepairsOptionalParams = { requestOptions: {} },
  ): Promise<RepairResult>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
public RepairResult scheduleRepairs(String widgetName, String problem, String contact);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type RepairInfo struct {
	Contact *string
	Problem *string
}

type RepairResult struct {
	Info    *string
	Reason  *string
}

type ClientScheduleRepairsResponse struct {
	RepairResult
}

type ClientScheduleRepairsOptions struct {}

func (client *Client) ScheduleRepairs(ctx context.Context, widgetName string, repairInfo RepairInfo, options *ClientScheduleRepairsOptions) (ClientScheduleRepairsResponse, error)

```

</ClientTabItem>
</ClientTabs>

If you want to keep the model, you have two options to prevent spreading:

- `@override`
- If you don't want to do client customizations, you could use a wrapper to explicitly set the body to prevent spread.

<ClientTabs>

<ClientTabItem lang="typespec" >

1. `@override`

The `@override` decorator allows you to replace the client method with the one in your service definition.

If your service definition spreads a model into the method signature, but you prefer that the generated client SDKs maintain the model intact, the `@override` decorator provides a solution.

Additionally, you can specify a language `scope` to limit the changes to a specific language emitter.

```tsp title=client.tsp
namespace Widget.Client;

op scheduleRepairs(
  body: RepairInfo,
  `api-version`: Azure.Core.Foundations.ApiVersionParameter,
): RepairResult;

@@override(Widget.Service.scheduleRepairs, Widget.Client.scheduleRepairs);
```

2. wrapper

If you prefer not to implement customizations in `client.tsp`, you can add `@bodyRoot` to the input in `main.tsp` prior to passing the model to the template.

```typespec title=main.tsp
namespace Widget.Service;

@resource("widgets")
model Widget {
  @key("widgetName")
  name: string;
}

model RepairInfo {
  problem: string;
  contact: string;
}

model RepairResult {
  reason: string;
  info: string;
}

alias Operations = Azure.Core.ResourceOperations<{}>;

alias BodyParameter<
  T,
  TName extends valueof string = "body",
  TDoc extends valueof string = "Body parameter."
> = {
  @doc(TDoc)
  @friendlyName(TName)
  @bodyRoot
  body: T;
};

op scheduleRepairs is Operations.ResourceAction<Widget, BodyParameter<RepairInfo>, RepairResult>;
```

</ClientTabItem>

<ClientTabItem lang="python" >
For Python, we will also generate the overloads described in the HTTP Post section, but will omit them for brevity.

```python
class RepairInfo:
  problem: str
  contact: str

class RepairResult:
  reason: str
  info: str

def scheduleRepairs(self, body: [Schema, JSON, IO[bytes]], *, content_type: str = "application/json") -> RepairResult:
  ...
```

</ClientTabItem>
<ClientTabItem lang="csharp" >

```csharp

```

</ClientTabItem>
<ClientTabItem lang="typescript" label="Typescript" >

```typescript
// JS CodeGen api layer
export async function scheduleRepairs(
  context: Client,
  widgetName: string,
  body: RepairInfo,
  options: ScheduleRepairsOptionalParams = { requestOptions: {} },
): Promise<RepairResult>;

// JS CodeGen classical client layer
export class WidgetServiceClient {
  scheduleRepairs(
    widgetName: string,
    body: RepairInfo,
    options: ScheduleRepairsOptionalParams = { requestOptions: {} },
  ): Promise<RepairResult>;
}
```

</ClientTabItem>
<ClientTabItem lang="java" >

```java
// Model class
@Immutable
public final class RepairInfo implements JsonSerializable<RepairInfo> {
    public RepairInfo(String problem, String contact);
    public String getProblem();
    public String getContact();
}

@Immutable
public final class RepairResult implements JsonSerializable<RepairResult> {
    public String getReason();
    public String getInfo();
}

// Client API
public RepairResult scheduleRepairs(String widgetName, RepairInfo body);
```

</ClientTabItem>
<ClientTabItem lang="go"  >

```go
type RepairInfo struct {
	Contact *string
	Problem *string
}

type RepairResult struct {
	Info    *string
	Reason  *string
}

type ServiceClientScheduleRepairsOptions struct {}

type ServiceClientScheduleRepairsResponse struct {
	RepairResult
}

func (client *Client) ScheduleRepairs(ctx context.Context, widgetName string, repairInfo RepairInfo, options *ClientScheduleRepairsOptions) (ClientScheduleRepairsResponse, error)
```

</ClientTabItem>
</ClientTabs>

## One path for multiple input/output

The following sections documents emitter behavior and customization when you use union operator `|` or `@sharedRoute` to express multiple input/output for a given path.

### Default behaviors

The simplest way to express a combination of input in TypeSpec is to use the union operator `|`.
At a glance, JS and Python supports natively union, while Java and C# will use overloads.

<ClientTabs>

```typespec title=client.tsp
@service(#{ title: "Analyze", version: "v1" })
namespace Analyze;
@route("/analyze")
@post
op analyze(@query mode: "strict" | "lenient", @body image: bytes): AnalyzeResult;

model CompletionInput {
  input: string | string[];
}

@route("/completions")
@post
op completions(@body input: CompletionInput): CompletionResult;
```

```python
def analyze(image: bytes, *, mode: Literal["strict", "lenient"]) -> AnalyzeResult:
  ...

class CompletionInput:
  input: Union[str, List[str]] = rest_field(readonly=True)

def completions(input: CompletionInput) -> CompletionResult:
  ...
```

```csharp
// Union "strict" | "lenient" will be generate as extensible enum
namespace Analyze.Models
{
  public readonly partial struct Mode : IEquatable<Mode>
  {
    public static Mode Strict { get; } = new Mode(StrictValue);
    public static Mode Lenient { get; } = new Mode(LenientValue);
  }
}

// other union which cannot be convert to enum will generate as BinaryData
namespace Analyze.Models
{
  public partial class CompletionInput
  {
    public CompletionInput(BinaryData input)
    public BinaryData Input { get; }
  }
}
namespace Analyze
{
  public partial class AnalyzeClient
  {
    //protocol method
    public virtual async Task<Response> AnalyzeAsync(string mode, RequestContent content, RequestContext context = null) {}
    public virtual Response Analyze(string mode, RequestContent content, RequestContext context = null) {}
    //convenience method
    public virtual async Task<Response<AnalyzeResult>> AnalyzeAsync(Mode mode, BinaryData image, CancellationToken cancellationToken = default) {}
    public virtual Response<AnalyzeResult> Analyze(Mode mode, BinaryData image, CancellationToken cancellationToken = default) {}


    //protocol method
    public virtual async Task<Response> CompletionsAsync(RequestContent content, RequestContext context = null) {}
    public virtual Response Completions(RequestContent content, RequestContext context = null) {}
    //convenience method
    public virtual async Task<Response<CompletionResult>> CompletionsAsync(CompletionInput input, CancellationToken cancellationToken = default) {}
    public virtual Response<CompletionResult> Completions(CompletionInput input, CancellationToken cancellationToken = default) {}

  }
}
```

```typescript
// JS CodeGen api layer
export async function completions(
  context: Client,
  input: CompletionInput,
  options: CompletionsOptionalParams = { requestOptions: {} },
): Promise<CompletionResult>;

export async function analyze(
  context: Client,
  mode: "strict" | "lenient",
  image: Uint8Array,
  options: AnalyzeOptionalParams = { requestOptions: {} },
): Promise<AnalyzeResult>;

// JS CodeGen classical client layer
export class AnalyzeClient {
  completions(
    input: CompletionInput,
    options: CompletionsOptionalParams = { requestOptions: {} },
  ): Promise<CompletionResult>;

  analyze(
    mode: "strict" | "lenient",
    image: Uint8Array,
    options: AnalyzeOptionalParams = { requestOptions: {} },
  ): Promise<AnalyzeResult>;
}
```

```java
public enum Mode {
    STRICT("strict"),
    LENIENT("lenient");
}

public final class CompletionInput {
    public CompletionInput(BinaryData input)
    public BinaryData getInput()
}

public final class AnalyzeClient {
    public Response<BinaryData> analyzeWithResponse(String mode, BinaryData image, RequestOptions requestOptions)
    public Response<BinaryData> completionsWithResponse(BinaryData input, RequestOptions requestOptions)
    public AnalyzeResult analyze(Mode mode, byte[] image)
    public CompletionResult completions(CompletionInput input)
}
```

```go
type AnalyzeResult struct {
	Confidence *float32
	Result     *string
}

type CompletionInput struct {
	Input []*string
}

type CompletionResult struct {
	Text   *string
	Tokens *int32
}

type AnalyzeClientAnalyzeOptions struct {}

type AnalyzeClientCompletionsOptions struct {}

type AnalyzeClientAnalyzeResponse struct {
	AnalyzeResult
}

type AnalyzeClientCompletionsResponse struct {
	CompletionResult
}

type AnalyzeRequestMode string

const (
	AnalyzeRequestModeLenient AnalyzeRequestMode = "lenient"
	AnalyzeRequestModeStrict AnalyzeRequestMode = "strict"
)

func (client *AnalyzeClient) Analyze(ctx context.Context, mode AnalyzeRequestMode, imageParam io.ReadSeekCloser, options *AnalyzeClientAnalyzeOptions) (AnalyzeClientAnalyzeResponse, error)

func (client *AnalyzeClient) Completions(ctx context.Context, input CompletionInput, options *AnalyzeClientCompletionsOptions) (AnalyzeClientCompletionsResponse, error)

```

</ClientTabs>

Using union implies that the entire combination of possible input is valid. If you have a specific set of combination, or connection between input and output,
you must use `@sharedRoute`. By default, codegen will generate one method per operation name.

<ClientTabs>

```typespec title=client.tsp
@sharedRoute
@route("/foo")
op a(x: int32): float;

@sharedRoute
@route("/foo")
op b(x: string): int64;
```

```python
def a(x: int) -> float:
  # code

def b(x: string) -> int:
  # code
```

```csharp
//protocol
public Response A(RequestContent content, RequestContext context);
public Response B(RequestContent content, RequestContext context);

//convenience
public Response<float> A(int x, CancellationToken token);
public Response<long> B(string x, Cancellation token);
```

```typescript
// JS CodeGen api layer
export async function a(
  context: Client,
  x: number,
  options: AOptionalParams = { requestOptions: {} },
): Promise<number>;

export async function b(
  context: Client,
  x: string,
  options: BOptionalParams = { requestOptions: {} },
): Promise<number>;

// JS CodeGen classical client layer
export class TestServiceClient {
  b(x: string, options: BOptionalParams = { requestOptions: {} }): Promise<number>;

  a(x: number, options: AOptionalParams = { requestOptions: {} }): Promise<number>;
}
```

```java
public final class Client {
    public Response<BinaryData> aWithResponse(BinaryData request, RequestOptions requestOptions)
    public Response<BinaryData> bWithResponse(BinaryData request, RequestOptions requestOptions)
    public double a(int x)
    public long b(String x)
}
```

```go
type ClientAOptions struct {}

type ClientBOptions struct {}

type ClientAResponse struct {
	Value *float32
}

type ClientBResponse struct {
	Value *int64
}

func (client *Client) A(ctx context.Context, x int32, options *ClientAOptions) (ClientAResponse, error)

func (client *Client) B(ctx context.Context, x string, options *ClientBOptions) (ClientBResponse, error)
```

</ClientTabs>

### Customizations

#### Merge `@sharedRoute` operations into one.

If your shared routes are actually one unique semantic operation, you may want to configure codegen to use a unique name. This is simply done by renaming both operations to the same name using `@clientName`

<ClientTabs>

```typespec
// main.tsp
@sharedRoute
@route("/foo")
op a(x: int) : float

@sharedRoute
@route("/foo")
op b(x: string) : int64

// client.tsp
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

@@clientName(a, "Foo");
@@clientName(b, "Foo");
```

```python
@overload
def foo(x: int) -> float:
   ...

@overload
def foo(x: string) -> int:
   ...

def foo(x: string | int) -> float | int:
   # Code here
```

```csharp
//protocol
public Response Foo(RequestContent content, RequestContext context);

//convenience
public Response<float> Foo(int x, CancellationToken token);
public Response<long> Foo(string x, Cancellation token);
```

```typescript
// NOT_SUPPORTED
```

```java
NOT_SUPPORTED
```

```go
// NOT_SUPPORTED
```

</ClientTabs>

## Conditional request headers

The following sections document how to generate client libraries for conditional request headers such as `If-Match` and `If-None-Match`.

<ClientTabs>

```typespec
model Response {
  name: string;
}

@get
op get(
  /** The request should only proceed if an entity matches this string. */
  @header("If-Match")
  ifMatch?: string,

  /** The request should only proceed if no entity matches this string. */
  @header("If-None-Match")
  ifNoneMatch?: string,
): Response;
```

```python
from azure.core import MatchConditions

def get(self, *, etag: Optional[str] = None, match_condition: Optional[MatchConditions] = None) -> Response:
```

```csharp
namespace TestService
{
  public partial class Response
  {
    public string Name { get; }
  }

  public partial class TestServiceClient
  {
    public TestServiceClient(Uri endpoint);
    // protocol method
    public virtual Response Get(MatchConditions matchConditions, RequestContext context);
    public virtual Task<Response> GetAsync(MatchConditions matchConditions, RequestContext context);
    // convenience method
    public virtual Response<Response> Get(MatchConditions matchConditions = default, CancellationToken cancellationToken = default);
    public virtual Task<Response<Response>> GetAsync(MatchConditions matchConditions = default, CancellationToken cancellationToken = default);
  }
}
```

```typescript
// JS CodeGen api layer
export async function get(
  context: Client,
  options: GetOptionalParams = { requestOptions: {} },
): Promise<Response>;

// JS CodeGen classical client layer
export class TestServiceClient {
  get(options: GetOptionalParams = { requestOptions: {} }): Promise<Response>;
}
```

```java
import com.azure.core.http.MatchConditions;

public Response get(MatchConditions matchConditions);
```

```go
type Response struct {
  Name string
}

type ClientGetOptions struct {
// The request should only proceed if an entity matches this string.
	IfMatch *string

// The request should only proceed if no entity matches this string.
	IfNoneMatch *string
}

func (client *Client) Get(ctx context.Context, options *ClientGetOptions) (*Response, error)

```

</ClientTabs>

## Using `@clientLocation` to control parameter placement

The `@clientLocation` decorator allows you to explicitly move parameters between client and operation levels.

### Moving subscriptionId from client to operation level

In ARM services, `subscriptionId` is automatically elevated to the client level. By applying `@clientLocation` to `subscriptionId` and explicitly moving it to an operation, you can move it back down to the method-level.

In the following case, since all instances of the subscription ID parameter have been explicitly moved onto the method-level, there is no longer a subscription ID parameter to the client.

<ClientTabs>

```typespec title="main.tsp"
@service
@armProviderNamespace
@versioned(Versions)
@armCommonTypesVersion(CommonTypes.Versions.v5)
namespace Microsoft.ContosoProviderHub;

/** Api versions */
enum Versions {
  /** 2024-04-01-preview api version */
  V2024_04_01_PREVIEW: "2024-04-01-preview",
}

@subscriptionResource
model MyModel is ProxyResource<{}> {
  @key("extendedZoneName")
  @segment("extendedZones")
  @path
  name: string;
}

op get is ArmResourceRead<MyModel>;
```

```typespec title="client.tsp"
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

// Move subscription ID from client to operation `get`
@@clientLocation(CommonTypes.SubscriptionIdParameter.subscriptionId, get);
```

```python
# Since all instances of subscription ID in the service have been moved to the operation level,
# there is no `subscription_id` parameter on the client
class ContosoProviderHubClient:
    def __init__(self, credential, **kwargs):
        ...

    def get(self, subscription_id: str, extended_zone_name: str, **kwargs) -> MyModel:
        ...
```

```csharp
// Main client with subscriptionId as client parameter
public partial class ContosoProviderHubClient
{
    public ContosoProviderHubClient(TokenCredential credential)
    {
        ...
    }

    public virtual Response<MyModel> Get(string subscriptionId, string extendedZoneName, CancellationToken cancellationToken = default)
    {
        ...
    }
}
```

```typescript
export class ContosoProviderHubClient {

  constructor(credential: TokenCredential) {
    ...
  }

  async get(subscriptionId: string, extendedZoneName: string): Promise<MyModel> {
    ...
  }
}
```

```java
public final class ContosoProviderHubClient {

    public ContosoProviderHubClient(TokenCredential credential) {
        ...
    }

    public MyModel get(String subscriptionId, String extendedZoneName) {
        ...
    }
}
```

```go
// subscriptionID is moved from the client to the operation level.
type ContosoProviderHubClient struct { ... }

func (c *ClientFactory) NewContosoProviderHubClient() *ContosoProviderHubClient

func (client *ContosoProviderHubClient) Get(ctx context.Context, subscriptionID string, extendedZoneName string, options *ContosoProviderHubClientGetOptions) (ContosoProviderHubClientGetResponse, error)
```

</ClientTabs>

:::caution
`@clientLocation` cannot move multiple parameters that share the same name but have **different types** to the same client. This commonly happens when `@clientLocation` is applied to a templated parameter that is instantiated with different types across operations. Doing so emits a `client-location-conflict` warning and produces a broken client where the parameter collapses to a single type. Move the parameter on each operation instead, so it keeps a consistent type on the client.
:::

## Customizing method signatures with `@override`

The `@override` decorator allows you to customize method signatures in generated client SDKs. This is useful when you need to:

- Make optional parameters required for certain languages
- Add language-specific convenience parameters
- Change the return type for better developer experience
- Group parameters into option bags
- Remove parameters that shouldn't be exposed in the client

### Basic usage

The `@override` decorator takes a target operation and a custom operation that defines the new signature:

```typespec
@@override(OriginalOperation, CustomOperation);
@@override(OriginalOperation, CustomOperation, "python"); // Language-specific
```

When applied, the method parameters come from the override operation while the underlying HTTP operation remains unchanged. TCGC maps method parameters to operation parameters based on name matching.

:::caution
The override operation must preserve every parameter that is realized as a path parameter in the original operation's HTTP route, keeping its `@path` decorator. Dropping such a parameter — or redeclaring it without `@path` — reports an `override-parameters-mismatch` error, because the underlying route still requires that value. To relocate a parameter instead of dropping it, use [`@clientLocation`](#using-clientlocation-to-control-parameter-placement).
:::

### Simple parameter customization

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="main.tsp"
@service
namespace MyService;

op getSecrets(@query maxResults?: int32): void;
```

```typespec title="client.tsp"
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

// Define operation with required parameter
op getSecretsCustom(@query maxResults: int32): void;

// Apply the override
@@override(MyService.getSecrets, getSecretsCustom);
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# maxResults is now required instead of optional
def get_secrets(self, max_results: int) -> None:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// maxResults is now required
public virtual Response GetSecrets(int maxResults, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// maxResults is now required
export async function getSecrets(maxResults: number): Promise<void>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// maxResults is now required
public void getSecrets(int maxResults);
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// maxResults is now required, exposed as a positional parameter.
func (client *MyServiceClient) GetSecrets(ctx context.Context, maxResults int32, options *MyServiceClientGetSecretsOptions) (MyServiceClientGetSecretsResponse, error)
```

</ClientTabItem>
</ClientTabs>

### Transformation functions (Experimental)

For composable customizations, TCGC provides experimental transformation functions that enable chainable modifications without manually defining custom operations.

:::caution
These functions are experimental and require suppressing the `experimental-feature` diagnostic.
:::

#### `replaceParameter`

Replace a parameter in an operation with a new parameter definition:

```typespec
extern fn replaceParameter(
  operation: Reflection.Operation,
  selector: valueof string | Reflection.ModelProperty,
  replacement: Reflection.ModelProperty
): Reflection.Operation;
```

##### Making a parameter required

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="main.tsp"
@service
namespace KeyVault;

op getSecrets(@query maxResults?: int32): void;
```

```typespec title="client.tsp"
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

model RequiredMaxResults {
  maxResults: int32;
}

#suppress "experimental-feature" "using replaceParameter"
@@override(
  KeyVault.getSecrets,
  replaceParameter(KeyVault.getSecrets, "maxResults", RequiredMaxResults.maxResults)
);
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# maxResults is now required
def get_secrets(self, max_results: int) -> None:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// maxResults is now required
public virtual Response GetSecrets(int maxResults, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// maxResults is now required
export async function getSecrets(maxResults: number): Promise<void>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// maxResults is now required
public void getSecrets(int maxResults);
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// maxResults is now required, exposed as a positional parameter.
func (client *MyServiceClient) GetSecrets(ctx context.Context, maxResults int32, options *MyServiceClientGetSecretsOptions) (MyServiceClientGetSecretsResponse, error)
```

</ClientTabItem>
</ClientTabs>

#### `removeParameter`

Remove a parameter from an operation:

```typespec
extern fn removeParameter(
  operation: Reflection.Operation,
  selector: valueof string | Reflection.ModelProperty
): Reflection.Operation;
```

When used with `@@override`, only optional parameters can be removed. Attempting to remove a required parameter will result in an error.

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="main.tsp"
@service
namespace KeyVault;

op getSecrets(@query maxResults?: int32): void;
```

```typespec title="client.tsp"
import "./main.tsp";
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

#suppress "experimental-feature" "using removeParameter"
@@override(KeyVault.getSecrets, removeParameter(KeyVault.getSecrets, "maxResults"));
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# maxResults parameter is removed
def get_secrets(self) -> None:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// maxResults parameter is removed
public virtual Response GetSecrets(CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// maxResults parameter is removed
export async function getSecrets(): Promise<void>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// maxResults parameter is removed
public void getSecrets();
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// maxResults parameter is removed.
func (client *MyServiceClient) GetSecrets(ctx context.Context, options *MyServiceClientGetSecretsOptions) (MyServiceClientGetSecretsResponse, error)
```

</ClientTabItem>
</ClientTabs>

#### `addParameter`

Add a new parameter to an operation:

```typespec
extern fn addParameter(
  operation: Reflection.Operation,
  parameter: Reflection.ModelProperty
): Reflection.Operation;
```

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="client.tsp"
model ConvenienceParams {
  @header("X-Request-Id") requestId?: string;
}

#suppress "experimental-feature" "using addParameter"
@@override(uploadFile, addParameter(uploadFile, ConvenienceParams.requestId));
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# requestId parameter is added
def upload_file(self, content: bytes, *, request_id: Optional[str] = None) -> None:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// requestId parameter is added
public virtual Response UploadFile(BinaryData content, string requestId = null, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// requestId parameter is added in options
export interface UploadFileOptions {
  requestId?: string;
}
export async function uploadFile(content: Uint8Array, options?: UploadFileOptions): Promise<void>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// requestId parameter is added
public void uploadFile(byte[] content, String requestId);
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// NOT_SUPPORTED
```

</ClientTabItem>
</ClientTabs>

#### `reorderParameters`

Reorder parameters of an operation according to a specified order:

```typespec
extern fn reorderParameters(
  operation: Reflection.Operation,
  order: valueof string[]
): Reflection.Operation;
```

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="main.tsp"
@service
namespace MyService;

op myOp(@query a: string, @query b: int32, @query c: boolean): void;
```

```typespec title="client.tsp"
// Reorder parameters: put 'c' first, then 'a', then 'b'
#suppress "experimental-feature" "using reorderParameters"
@@override(MyService.myOp, reorderParameters(MyService.myOp, #["c", "a", "b"]));
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# Parameters are now in the order: c, a, b
def my_op(self, c: bool, a: str, b: int) -> None:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// Parameters are now in the order: c, a, b
public virtual Response MyOp(bool c, string a, int b, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// Parameters are now in the order: c, a, b
export async function myOp(c: boolean, a: string, b: number): Promise<void>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// Parameters are now in the order: c, a, b
public void myOp(boolean c, String a, int b);
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// Parameters are now in the order: c, a, b.
func (client *MyServiceClient) MyOp(ctx context.Context, c bool, a string, b int32, options *MyServiceClientMyOpOptions) (MyServiceClientMyOpResponse, error)
```

</ClientTabItem>
</ClientTabs>

### Chaining transformations

Transformation functions can be chained together. Each function returns a new operation that can be passed to the next transformation:

<ClientTabs>
<ClientTabItem lang="typespec">

```typespec title="client.tsp"
@service
namespace MyService;

op search(@query query?: string, @query limit?: int32): string;

model RequiredParams {
  query: string;
  limit: int32;
}

// Chain: make query required -> make limit required -> reorder parameters
#suppress "experimental-feature" "using replaceParameter"
alias step1 = replaceParameter(search, "query", RequiredParams.query);
#suppress "experimental-feature" "using replaceParameter"
alias step2 = replaceParameter(step1, "limit", RequiredParams.limit);
#suppress "experimental-feature" "using reorderParameters"
@@override(search, reorderParameters(step2, #["limit", "query"]));
```

</ClientTabItem>
<ClientTabItem lang="python">

```python
# Both query and limit are now required, and limit comes before query
def search(self, limit: int, query: str) -> str:
    ...
```

</ClientTabItem>
<ClientTabItem lang="csharp">

```csharp
// Both parameters required, limit comes before query
public virtual Response<string> Search(int limit, string query, CancellationToken cancellationToken = default)
```

</ClientTabItem>
<ClientTabItem lang="typescript">

```typescript
// Both parameters required, limit comes before query
export async function search(limit: number, query: string): Promise<string>;
```

</ClientTabItem>
<ClientTabItem lang="java">

```java
// Both parameters required, limit comes before query
public String search(int limit, String query);
```

</ClientTabItem>
<ClientTabItem lang="go">

```go
// NOT_SUPPORTED
```

</ClientTabItem>
</ClientTabs>

### Language-specific customizations

Use the `scope` parameter to apply customizations only to specific language emitters:

```typespec
// Only apply to Python - maxResults will be required in Python but remain optional in other languages
#suppress "experimental-feature" "using replaceParameter"
@@override(
  getSecrets,
  replaceParameter(getSecrets, "maxResults", RequiredMaxResults.maxResults),
  "python"
);
```

Supported scope values include: `"python"`, `"csharp"`, `"java"`, `"javascript"`, `"go"`.

## HEAD Operations with Boolean Response (`@responseAsBool`)

For HEAD operations, you can use `@responseAsBool` to model the response as a boolean value. A successful response (2xx) returns `true`, and a 404 response returns `false` instead of throwing an error.

<ClientTabs>

```typespec
import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

@responseAsBool
@head
@route("/widgets/{name}")
op exists(@path name: string): void;
```

```python
def exists(self, name: str, **kwargs: Any) -> bool:
    ...
```

```csharp
public virtual Response<bool> Exists(string name, CancellationToken cancellationToken = default);
public virtual async Task<Response<bool>> ExistsAsync(string name, CancellationToken cancellationToken = default);
```

```typescript
export async function exists(
  context: Client,
  name: string,
  options?: ExistsOptionalParams,
): Promise<boolean>;
```

```java
public boolean exists(String name);
public Response<Boolean> existsWithResponse(String name, RequestOptions requestOptions);
```

```go
// NOT_SUPPORTED
```

</ClientTabs>

When this decorator is applied:

- The method returns a `boolean` value — this is a purely client-side concept computed from the HTTP status code
- A successful response (2xx) means the method returns `true`
- A 404 response means the method returns `false` (instead of throwing an error)
- The HTTP-level response has no body type; the boolean is derived entirely from the status code
- If the operation has no explicit 404 response, one is automatically added

:::note
This decorator can only be applied to HEAD operations. Applying it to operations with other HTTP verbs will result in an error.
:::
