RestSharp C# API Automation: Complete 2026 Guide
Complete RestSharp C# API automation guide for 2026. Setup, CRUD operations, authentication, schema validation, mocking, and CI/CD integration.

In this article
- What is RestSharp?
- Step 1 — Install RestSharp
- Step 2 — Your First GET Request
- Step 3 — Deserialize JSON
- Step 4 — POST Requests
- Step 5 — PUT and DELETE
- Step 6 — Authentication
- Step 7 — Query Parameters
- Step 8 — Schema Validation
- Step 9 — Reusable Client Setup
- Step 10 — Mocking with WireMock
- Step 11 — CI/CD Integration
- Best Practices
- Common RestSharp Mistakes and Fixes
- Continue your API automation journey
- Frequently asked questions
Last updated: June 27, 2026 · 9 min read
This guide covers everything you need to automate API testing with RestSharp in C#: setup, CRUD operations, authentication, schema validation, mocking, and CI/CD integration. Pair it with our API Testing Tutorial, RestSharp C# fundamentals, and REST Assured Java guide.
What is RestSharp?
RestSharp is a simple REST and HTTP API client for .NET. It wraps HttpClient with a fluent API that handles JSON serialization, authentication, and error handling out of the box. Docs: restsharp.dev.
Step 1 — Install RestSharp
dotnet new nunit -n RestSharpDemo
cd RestSharpDemo
dotnet add package RestSharp
dotnet add package Newtonsoft.JsonStep 2 — Your First GET Request
using RestSharp;
using NUnit.Framework;
public class UserApiTests
{
private RestClient _client;
[SetUp]
public void SetUp()
{
_client = new RestClient("https://jsonplaceholder.typicode.com");
}
[Test]
public void GetUserById()
{
var request = new RestRequest("/users/{id}", Method.Get);
request.AddUrlSegment("id", "1");
var response = _client.Execute(request);
Assert.That(response.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(response.Content, Does.Contain("Leanne Graham"));
}
}Step 3 — Deserialize JSON
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
[Test]
public void GetUserByIdDeserialized()
{
var request = new RestRequest("/users/{id}", Method.Get);
request.AddUrlSegment("id", "1");
var response = _client.Execute<User>(request);
Assert.That(response.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(response.Data.Name, Is.EqualTo("Leanne Graham"));
Assert.That(response.Data.Email, Does.Contain("@"));
}Step 4 — POST Requests
[Test]
public void CreateUser()
{
var request = new RestRequest("/users", Method.Post)
.AddJsonBody(new
{
name = "Alice Johnson",
email = "alice@example.com",
role = "admin"
});
var response = _client.Execute(request);
Assert.That((int)response.StatusCode, Is.EqualTo(201));
var json = JObject.Parse(response.Content);
Assert.That(json["email"]?.ToString(), Is.EqualTo("alice@example.com"));
}Step 5 — PUT and DELETE
[Test]
public void UpdateUser()
{
var request = new RestRequest("/users/{id}", Method.Put)
.AddUrlSegment("id", "1")
.AddJsonBody(new { name = "Alice Updated" });
var response = _client.Execute(request);
Assert.That((int)response.StatusCode, Is.EqualTo(200));
}
[Test]
public void DeleteUser()
{
var request = new RestRequest("/users/{id}", Method.Delete)
.AddUrlSegment("id", "1");
var response = _client.Execute(request);
Assert.That((int)response.StatusCode, Is.EqualTo(200).Or.EqualTo(204));
}Step 6 — Authentication
Bearer Token
[Test]
public void AuthenticatedRequest()
{
var token = GetAuthToken();
_client.AddDefaultHeader("Authorization", $"Bearer {token}");
var request = new RestRequest("/admin/users", Method.Get);
var response = _client.Execute(request);
Assert.That((int)response.StatusCode, Is.EqualTo(200));
}
private string GetAuthToken()
{
var authRequest = new RestRequest("/auth/login", Method.Post)
.AddJsonBody(new { email = "admin@example.com", password = "Sup3rSecret!" });
return _client.Execute<TokenResponse>(authRequest).Data.Token;
}
public class TokenResponse
{
public string Token { get; set; }
}Basic Auth
_client.Authenticator = new HttpBasicAuthenticator("admin", "Sup3rSecret!");Step 7 — Query Parameters
var request = new RestRequest("/users", Method.Get)
.AddQueryParameter("page", "1")
.AddQueryParameter("limit", "10");Step 8 — Schema Validation
Use Newtonsoft.Json.Schema:
dotnet add package Newtonsoft.Json.Schema[Test]
public void ValidateResponseSchema()
{
var schemaJson = File.ReadAllText("schemas/user.json");
var schema = JSchema.Parse(schemaJson);
var request = new RestRequest("/users/{id}", Method.Get)
.AddUrlSegment("id", "1");
var response = _client.Execute(request);
var json = JObject.Parse(response.Content);
var isValid = json.IsValid(schema, out var errors);
Assert.That(isValid, Is.True, $"Schema validation failed: {string.Join(", ", errors)}");
}Step 9 — Reusable Client Setup
public class ApiClient
{
public RestClient Client { get; }
public ApiClient(string baseUrl)
{
Client = new RestClient(baseUrl);
}
public async Task<RestResponse<T>> GetAsync<T>(string resource)
{
return await Client.ExecuteAsync<T>(new RestRequest(resource, Method.Get));
}
public async Task<RestResponse<T>> PostAsync<T>(string resource, object body)
{
var request = new RestRequest(resource, Method.Post).AddJsonBody(body);
return await Client.ExecuteAsync<T>(request);
}
public async Task<RestResponse> DeleteAsync(string resource)
{
return await Client.ExecuteAsync(new RestRequest(resource, Method.Delete));
}
}Step 10 — Mocking with WireMock
dotnet add package WireMock.Netpublic class MockedApiTests
{
private WireMockServer _server;
private RestClient _client;
[SetUp]
public void SetUp()
{
_server = WireMockServer.Start(8080);
_server.Given(Request.Create().WithPath("/api/users/1").UsingGet())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody("{ \"id\": 1, \"name\": \"Mock User\" }"));
_client = new RestClient("http://localhost:8080");
}
[TearDown]
public void TearDown() { _server.Stop(); }
[Test]
public void TestAgainstMock()
{
var request = new RestRequest("/api/users/1", Method.Get);
var response = _client.Execute(request);
Assert.That((int)response.StatusCode, Is.EqualTo(200));
}
}See more options in our free API mocking tools roundup.
Step 11 — CI/CD Integration
GitHub Actions
name: RestSharp Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '8.0.x' }
- run: dotnet restore
- run: dotnet test --logger "trx;LogFileName=results.trx"
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: test-results
path: TestResults/For deeper pipeline patterns, see our CI/CD pipeline testing tutorial and GitHub Actions for automation testing guide.
Best Practices
Do
- Use async/await for scalability
- Validate response schemas on every test
- Use mocks for external dependencies
- Store credentials in secrets, not source
- Track metrics (response time, error rate)
Don't
- Don't hardcode URLs or credentials
- Don't chain tests that depend on each other
- Don't ignore HTTP error codes
- Don't skip schema validation
Common RestSharp Mistakes and Fixes
Mistake 1 — Not using async
// BAD
var response = client.Execute(request);
// GOOD
var response = await client.ExecuteAsync(request);Mistake 2 — Hardcoded URLs
// BAD
var client = new RestClient("https://api.example.com");
// GOOD
var baseUrl = Environment.GetEnvironmentVariable("API_BASE_URL") ?? "https://staging.example.com";
var client = new RestClient(baseUrl);Mistake 3 — Ignoring HTTP status codes
if (!response.IsSuccessful) {
Assert.Fail($"Request failed: {response.StatusCode} - {response.ErrorMessage}");
}Mistake 4 — Not validating response schema
var schema = JSchema.Parse(File.ReadAllText("schemas/user.json"));
var body = JObject.Parse(response.Content);
Assert.That(body.IsValid(schema), Is.True);Mistake 5 — Sharing state across tests
Use fresh client instances per test. Don't share state via static fields.
Mistake 6 — Not handling rate limits
public async Task<RestResponse> ExecuteWithRetry(RestRequest request)
{
for (int i = 0; i < 3; i++)
{
var response = await client.ExecuteAsync(request);
if (response.StatusCode != HttpStatusCode.TooManyRequests)
return response;
await Task.Delay(1000 * (i + 1));
}
throw new Exception("Rate limit exceeded");
}Mistake 7 — Not logging failures
if (!response.IsSuccessful) {
Log.Error($"Request: {request.Method} {request.Resource}");
Log.Error($"Response: {response.StatusCode} {response.Content}");
}Continue your API automation journey
Frequently asked questions
Is RestSharp still relevant in 2026?
Yes — RestSharp v110+ is actively maintained. It's the most popular HTTP client for .NET API testing.
RestSharp vs HttpClient — which should I use?
Use RestSharp for API testing (less boilerplate). Use HttpClient for production code (more control).
Can RestSharp deserialize JSON automatically?
Yes — pass a type to ExecuteAsync<T>() and RestSharp handles JSON deserialization.
How do I mock APIs in RestSharp tests?
Use WireMock.Net for full mocking, or stub responses with a local test server.
How do I handle rate limiting in tests?
Implement retry logic with exponential backoff, or use a sandbox API that doesn't rate-limit.
Is RestSharp free?
Yes — RestSharp is free and open source under the Apache 2.0 license.
Practice these questions
Rehearse REST, Postman, REST Assured and contract-testing questions with worked examples.
Was this article helpful?
Keep building your QA edge
Pillar guides- Postman TutorialPostman tutorial for testersPostman from zero to CI — collections, scripts, Newman.
- AI Mock Interviewpractice these questions with our AI mock interviewLive AI-powered mock interviews with rubric feedback.
- ATS Resume Reviewcheck your ATS score instantlyFree AI ATS scoring with rewrite suggestions.
Continue reading
Join the QA Community
Connect with fellow testers, share job leads, and get career advice.
Stop Reinventing the Wheel. Upgrade Your QA Arsenal.
Take your testing skills from beginner to Lead Engineer. Supercharge your daily workflow with our premium digital resources.
- ⚡ Ready-to-use testing strategy templates
- 🔥 Advanced API & UI automation guides
- ⏱️ Save 10+ hours a week on test planning


