Modernized C# client for Bitbucket Server (Stash) REST API.
Fork notice — This is an actively maintained fork of lvermeulen/Bitbucket.Net, which appears to be abandoned (last release 2020). The fork is not production-ready yet — it works well for the author's own use case (an MCP Server for on-prem Bitbucket Server) but not every endpoint has been fully tested. Contributions, bug reports, and feedback are very welcome.
- .NET 10 target (dropped .NET Framework / .NET Standard)
System.Text.Jsoninstead of Newtonsoft.Json (2-3x faster, no CVEs)CancellationTokenon every async methodIAsyncEnumerablestreaming for paginated endpoints- Streaming diffs and raw file content
- Typed exception hierarchy (
BitbucketNotFoundException, etc.) IHttpClientFactory/ DI-friendly constructors- Bitbucket Server 9.0+ blocker-comment (task) support with legacy fallback
- Flurl.Http 4.x
If you're looking for Bitbucket Cloud API, try this repository.
dotnet add package BitbucketServer.Net --prereleasevar client = new BitbucketClient("https://bitbucket.example.com", "username", "password");var client = new BitbucketClient("https://bitbucket.example.com", () => GetAccessToken());For production scenarios, you can inject an externally managed HttpClient to leverage IHttpClientFactory for connection pooling, resilience policies (via Polly), and centralized configuration:
// In Program.cs or Startup.cs
services.AddHttpClient<BitbucketClient>(client =>
{
client.Timeout = TimeSpan.FromMinutes(2);
})
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.AddTransientHttpErrorPolicy(p =>
p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
// Register BitbucketClient
services.AddSingleton<BitbucketClient>(sp =>
{
var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(nameof(BitbucketClient));
return new BitbucketClient(
httpClient,
"https://bitbucket.example.com",
() => sp.GetRequiredService<ITokenProvider>().GetToken());
});For fine-grained control over Flurl's configuration:
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache()
.Add("Bitbucket", "https://bitbucket.example.com", builder => builder
.WithSettings(s => s.Timeout = TimeSpan.FromMinutes(5))
.WithHeader("X-Custom-Header", "value")));
services.AddSingleton<BitbucketClient>(sp =>
{
var flurlClient = sp.GetRequiredService<IFlurlClientCache>().Get("Bitbucket");
return new BitbucketClient(flurlClient, () => GetToken());
});For memory-efficient processing of large result sets, use the streaming variants:
// Stream projects without buffering all pages in memory
await foreach (var project in client.GetProjectsStreamAsync())
{
Console.WriteLine(project.Name);
}
// With cancellation support
var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
await foreach (var pr in client.GetPullRequestsStreamAsync("PROJ", "repo", cancellationToken: cts.Token))
{
await ProcessPullRequestAsync(pr);
}The library provides typed exceptions for precise error handling:
try
{
var repo = await client.GetRepositoryAsync("PROJ", "repo");
}
catch (BitbucketNotFoundException ex)
{
Console.WriteLine($"Repository not found: {ex.Context}");
}
catch (BitbucketAuthenticationException)
{
Console.WriteLine("Invalid credentials");
}
catch (BitbucketForbiddenException ex)
{
Console.WriteLine($"Access denied: {ex.Message}");
}
catch (BitbucketApiException ex)
{
Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}Performance benchmarks are available in the benchmarks/ folder using BenchmarkDotNet:
cd benchmarks/Bitbucket.Net.Benchmarks
dotnet run -c ReleaseSee benchmarks/README.md for detailed instructions.
- Audit
- Project Events
- Repository Events
- Branches
- Create Branch
- Delete Branch
- Branch Info
- Branch Model
- Builds
- Commits Build Stats
- Commit Build Stats
- Commit Build Status
- Associate Build Status
- Comment Likes
- Repository Comment Likes
- Pull Request Comment Likes
- Core
- Admin
- Groups
- Users
- Cluster
- License
- Mail Server
- Permissions
- Pull Requests
- Application Properties
- Dashboard
- Groups
- Hooks
- Inbox
- Logs
- Markup
- Profile
- Projects
- Projects
- Permissions
- Repos
- Repos
- Branches
- Browse
- Changes
- Commits
- Compare
- Diff
- Files
- Last Modified
- Participants
- Permissions
- Pull Requests
- Raw
- Settings
- Tags
- Webhooks
- Settings
- Repos
- Tasks
- Users
- Admin
- Default Reviewers
- Project Default Reviewers
- Repository Default Reviewers
- Git
- JIRA
- Create JIRA Issue
- Get Commits For JIRA Issue
- Get JIRA Issues For Commits
- Personal Access Tokens
- Ref Restrictions
- Project Restrictions
- Repository Restrictions
- Repository Ref Synchronization
- SSH
