Served.SDK
1.2.0
See the version list below for details.
dotnet add package Served.SDK --version 1.2.0
NuGet\Install-Package Served.SDK -Version 1.2.0
<PackageReference Include="Served.SDK" Version="1.2.0" />
<PackageVersion Include="Served.SDK" Version="1.2.0" />
<PackageReference Include="Served.SDK" />
paket add Served.SDK --version 1.2.0
#r "nuget: Served.SDK, 1.2.0"
#:package Served.SDK@1.2.0
#addin nuget:?package=Served.SDK&version=1.2.0
#tool nuget:?package=Served.SDK&version=1.2.0
Served.SDK
The official .NET SDK for the Served API. This library provides a strongly-typed, modern fluent client for interacting with the Served platform, covering Project Management, Task Tracking, Time Registration, Finance, DevOps, and more.
Features
- Module-Based API: Organized access through domain modules (e.g.,
client.ProjectManagement.Projects). - Generic & Abstract: Built on reusable base classes for consistent CRUD operations.
- Strongly Typed: Full type safety for all Served entities (Projects, Tasks, Invoices, etc.).
- Modern Async: Built from the ground up with
async/await. - Bulk Operations: Support for batch create, update, and delete operations.
- Error Handling: Custom
ServedApiExceptionprovides detailed error context. - Backwards Compatible: Legacy client access patterns still supported.
- Tracing & Observability: Built-in OpenTelemetry support with Forge platform integration.
Installation
dotnet add package Served.SDK
Getting Started
Initialization
Initialize the ServedClient with your API URL, Token, and optional Tenant context.
using Served.SDK.Client;
var client = new ServedClient(
baseUrl: "https://app.served.dk",
token: "YOUR_API_TOKEN",
tenant: "YOUR_TENANT_SLUG" // Optional header context
);
Dependency Injection
For ASP.NET Core applications:
services.AddHttpClient<IServedClient, ServedClient>(client =>
{
client.BaseAddress = new Uri("https://app.served.dk");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "TOKEN");
});
API Structure
The SDK organizes APIs into domain modules for better discoverability:
| Module | Resources | Description |
|---|---|---|
ProjectManagement |
Projects, Tasks | Project and task management |
DevOpsModule |
Repositories, PullRequests, Pipelines | DevOps integration |
FinanceModule |
Invoices | Invoice management |
SalesModule |
Pipelines, Deals | Sales pipeline and deals |
Registration |
TimeRegistrations | Time tracking |
Companies |
Customers | Customer management |
Identity |
Employees, ApiKeys | User and API key management |
Calendar |
Agreements | Appointments and agreements |
Board |
Boards, Sheets | Kanban boards |
Reporting |
Dashboards, Datasources | Reports and dashboards |
Tenant |
Tenants, Workspaces | Multi-tenant management |
Bootstrap |
- | Application initialization |
Usage Examples
Module-Based Access (Recommended)
// Project Management
var projects = await client.ProjectManagement.Projects.GetAllAsync();
var tasks = await client.ProjectManagement.Tasks.GetByProjectAsync(123);
// Time Registration
var registrations = await client.Registration.TimeRegistrations.GetByDateRangeAsync(
"2024-01-01", "2024-01-31");
// Calendar
var agreements = await client.Calendar.Agreements.GetByCustomerAsync(456);
// DevOps
var repos = await client.DevOpsModule.Repositories.GetAllAsync();
var pipelines = await client.DevOpsModule.Pipelines.GetByRepositoryAsync(789);
Projects
Manage projects with the client.ProjectManagement.Projects resource.
using Served.SDK.Models.Projects;
// 1. List Projects (with filtering)
var projects = await client.ProjectManagement.Projects.GetAllAsync(new ProjectQueryParams
{
CustomerId = 123,
IsActive = true,
Take = 50
});
// 2. Get Project Details
var project = await client.ProjectManagement.Projects.GetAsync(projectId: 1);
Console.WriteLine($"Project: {project.Name} (#{project.ProjectNo})");
// 3. Create a Project
var newProject = await client.ProjectManagement.Projects.CreateAsync(new CreateProjectRequest
{
Name = "New Website Launch",
StartDate = DateTime.UtcNow,
EndDate = DateTime.UtcNow.AddMonths(3),
CustomerId = 123
});
// 4. Update Project
await client.ProjectManagement.Projects.UpdateAsync(newProject.Id, new UpdateProjectRequest
{
Description = "Updated description",
Progress = 50
});
// 5. Delete Project
await client.ProjectManagement.Projects.DeleteAsync(projectId: 1);
// 6. Bulk Operations
var bulkResult = await client.ProjectManagement.Projects.CreateBulkAsync(new BulkCreateProjectsRequest
{
Projects = new List<CreateProjectRequest>
{
new() { Name = "Project A", CustomerId = 1 },
new() { Name = "Project B", CustomerId = 1 }
}
});
Tasks
Manage tasks with client.ProjectManagement.Tasks.
using Served.SDK.Models.Tasks;
// 1. List Tasks (with filtering)
var tasks = await client.ProjectManagement.Tasks.GetAllAsync(new TaskQueryParams
{
ProjectId = project.Id,
IncludeCompleted = false,
Take = 50
});
// 2. Get Task Details
var task = await client.ProjectManagement.Tasks.GetAsync(taskId: 1);
// 3. Create a Task
var newTask = await client.ProjectManagement.Tasks.CreateAsync(new CreateTaskRequest
{
Name = "Design Homepage",
ProjectId = project.Id,
DueDate = DateTime.UtcNow.AddDays(7),
Priority = TaskPriority.High
});
// 4. Update Task
await client.ProjectManagement.Tasks.UpdateAsync(newTask.Id, new UpdateTaskRequest
{
Description = "Create mockups for homepage",
Status = TaskStatus.InProgress
});
// 5. Update Task Status
await client.ProjectManagement.Tasks.UpdateStatusAsync(newTask.Id, new UpdateTaskStatusRequest
{
Status = TaskStatus.Completed
});
// 6. Get Tasks by Project
var projectTasks = await client.ProjectManagement.Tasks.GetByProjectAsync(project.Id);
// 7. Bulk Status Update
await client.ProjectManagement.Tasks.UpdateStatusBulkAsync(new BulkUpdateTaskStatusRequest
{
Ids = new List<int> { 1, 2, 3 },
Status = TaskStatus.Completed
});
Time Registration
Log hours using client.Registration.TimeRegistrations.
using Served.SDK.Models.TimeRegistration;
// 1. Create Time Registration
var registration = await client.Registration.TimeRegistrations.CreateAsync(new CreateTimeRegistrationRequest
{
TaskId = task.Id,
ProjectId = project.Id,
Start = DateTime.UtcNow.AddHours(-2),
End = DateTime.UtcNow,
Minutes = 120,
Description = "Worked on design mockups",
Billable = true
});
// 2. Get Time Registrations by Project
var registrations = await client.Registration.TimeRegistrations.GetByProjectAsync(project.Id);
// 3. Get Time Registrations by Date Range
var weekRegistrations = await client.Registration.TimeRegistrations.GetByDateRangeAsync(
"2024-01-01", "2024-01-07");
// 4. Get Time Registrations by Employee
var myRegistrations = await client.Registration.TimeRegistrations.GetByEmployeeAsync(employeeId: 123);
// 5. Bulk Create
await client.Registration.TimeRegistrations.CreateBulkAsync(new BulkCreateTimeRegistrationsRequest
{
Items = new List<CreateTimeRegistrationRequest>
{
new() { ProjectId = 1, Minutes = 60, Description = "Meeting" },
new() { ProjectId = 1, Minutes = 120, Description = "Development" }
}
});
Customers
Manage customers with client.Companies.Customers.
using Served.SDK.Models.Customers;
// 1. List Customers
var customers = await client.Companies.Customers.GetAllAsync(new CustomerQueryParams
{
IsActive = true,
CustomerType = CustomerType.Company
});
// 2. Create Customer
var customer = await client.Companies.Customers.CreateAsync(new CreateCustomerRequest
{
Name = "Acme Corporation",
Email = "contact@acme.com",
CustomerType = CustomerType.Company
});
// 3. Search Customers
var results = await client.Companies.Customers.SearchAsync("Acme");
Calendar (Agreements)
Manage appointments with client.Calendar.Agreements.
using Served.SDK.Models.Agreements;
// 1. Get Agreements by Date Range
var appointments = await client.Calendar.Agreements.GetByDateRangeAsync(
DateTime.Today, DateTime.Today.AddDays(7));
// 2. Create Agreement
var agreement = await client.Calendar.Agreements.CreateAsync(new CreateAgreementRequest
{
Title = "Project Kickoff Meeting",
StartDate = DateTime.UtcNow.AddDays(1),
EndDate = DateTime.UtcNow.AddDays(1).AddHours(2),
CustomerId = customer.Id
});
// 3. Get Agreements by Customer
var customerMeetings = await client.Calendar.Agreements.GetByCustomerAsync(customer.Id);
DevOps
Access DevOps integrations with client.DevOpsModule.
using Served.SDK.Models.DevOps;
// 1. List Repositories
var repos = await client.DevOpsModule.Repositories.GetAllAsync();
// 2. Get Pull Requests
var pullRequests = await client.DevOpsModule.PullRequests.GetByRepositoryAsync(repoId: 1);
// 3. Get Pipelines
var pipelines = await client.DevOpsModule.Pipelines.GetByRepositoryAsync(repoId: 1);
Finance (Invoices)
Access invoice data with client.FinanceModule.
using Served.SDK.Models.Finance;
// Get invoice keys and fetch details
var invoiceKeys = await client.FinanceModule.Invoices.GetKeysAsync(new InvoiceQueryParams
{
Take = 10
});
var invoices = await client.FinanceModule.Invoices.GetRangeAsync(invoiceKeys);
foreach (var invoice in invoices)
{
Console.WriteLine($"Invoice #{invoice.InvoiceNo}: {invoice.Amount:C} ({invoice.StatusName})");
}
Identity (Employees & API Keys)
Manage users and API keys with client.Identity.
using Served.SDK.Models.Users;
using Served.SDK.Models.ApiKeys;
// Get Employees
var employees = await client.Identity.Employees.GetAllAsync();
// Manage API Keys
var apiKeys = await client.Identity.ApiKeys.GetAllAsync();
var newKey = await client.Identity.ApiKeys.CreateAsync(new CreateApiKeyRequest
{
Name = "CI/CD Integration",
Scopes = new List<string> { "projects:read", "tasks:write" }
});
Legacy Access (Backwards Compatible)
The original flat client access is still supported:
// Legacy access pattern (still works)
var projects = await client.Projects.GetAllAsync();
var tasks = await client.Tasks.GetAllAsync();
var customers = await client.Customers.GetAllAsync();
Error Handling
The SDK throws ServedApiException for non-success HTTP status codes.
try
{
await client.ProjectManagement.Projects.GetAsync(99999);
}
catch (ServedApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
Console.WriteLine("Project not found.");
}
catch (ServedApiException ex)
{
Console.WriteLine($"API Error: {ex.StatusCode} - {ex.Content}");
}
Tracing & Observability
The SDK includes built-in tracing with OpenTelemetry support and Forge platform integration.
Quick Start
// Enable tracing with environment auto-detection
var client = new ServedClient("https://api.served.dk", token)
.EnableTracing();
// Or use the builder pattern for full control
var client = new ServedClientBuilder()
.WithBaseUrl("https://api.served.dk")
.WithToken(token)
.WithTenant("my-workspace")
.WithTracing(options =>
{
options.ServiceName = "my-application";
options.EnableForge = true;
options.SamplingRate = 0.1; // Sample 10% of requests
})
.Build();
Environment Variables
| Variable | Description | Default |
|---|---|---|
SERVED_TRACING_ENABLED |
Enable/disable tracing | false |
SERVED_SERVICE_NAME |
Service identifier | served-sdk-client |
SERVED_SERVICE_VERSION |
Service version | SDK version |
SERVED_ENVIRONMENT |
Environment name | development |
FORGE_API_KEY |
Forge platform API key | - |
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP collector endpoint | - |
SERVED_SAMPLING_RATE |
Request sampling rate (0.0-1.0) | 1.0 |
Custom Events
// Record custom telemetry events
client.Tracer?.RecordEvent(new TelemetryEvent
{
Type = TelemetryEventType.Custom,
Name = "invoice.generated",
Attributes = new Dictionary<string, object>
{
["invoice.id"] = invoiceId,
["invoice.amount"] = amount
}
});
Manual Spans
// Create custom spans for complex operations
using var span = client.Tracer?.StartSpan("batch-import");
span?.SetAttribute("batch.size", items.Count);
foreach (var item in items)
{
await ProcessItemAsync(item);
}
Architecture
Core Components
IHttpClient: Interface for HTTP operations used by all API clients.ApiClientBase<TEntity, TDetail, TCreate, TUpdate, TQuery>: Generic base class for CRUD operations.BulkApiClientBase: Extended base class with bulk operation support.ApiModuleBase: Base class for organizing related resources into modules.
Project Structure
Served.SDK/
├── Client/
│ ├── Core/
│ │ ├── IHttpClient.cs # HTTP operations interface
│ │ ├── IApiClient.cs # Generic API client interfaces
│ │ ├── ApiClientBase.cs # Abstract CRUD implementation
│ │ └── ApiModuleBase.cs # Module grouping base class
│ ├── Apis/
│ │ ├── ProjectManagementApi.cs # Projects & Tasks
│ │ ├── DevOpsApi.cs # Repositories, PRs, Pipelines
│ │ ├── FinanceApi.cs # Invoices
│ │ ├── SalesApi.cs # Sales Pipelines & Deals
│ │ ├── RegistrationApi.cs # Time Registration
│ │ ├── CompaniesApi.cs # Customers
│ │ ├── IdentityApi.cs # Employees & API Keys
│ │ ├── CalendarApi.cs # Agreements
│ │ ├── BoardApi.cs # Boards & Sheets
│ │ ├── ReportingApi.cs # Dashboards & Datasources
│ │ ├── TenantApi.cs # Tenants & Workspaces
│ │ └── BootstrapApi.cs # Initialization
│ ├── Resources/ # Legacy resource clients
│ ├── ServedClient.cs # Main client implementation
│ └── IServedClient.cs # Client interface
└── Models/
├── Projects/
├── Tasks/
├── TimeRegistration/
├── Customers/
├── Agreements/
├── Finance/
├── DevOps/
└── Common/
Support
For issues, please open a ticket on the GitHub Repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Playwright (>= 1.49.0)
- Newtonsoft.Json (>= 13.0.4)
- OpenTelemetry (>= 1.8.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.8.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.2.0: Added MCP utilities (ToolArgs, ResponseFormatter, DocumentParser, DictToolArgs) for consistent parameter parsing and markdown response formatting. Reduces token usage in AI interactions.