.NET SDK β Client Reference: ProjectsClient (Projects AKA Agents)ΒΆ
OverviewΒΆ
ProjectsClient provides methods to retrieve and manage projects (also called agents). You can:
- List a userβs projects and services.
- Retrieve a specific project or find by name.
- Create, update, and delete projects.
- Fetch project service hierarchies and service listings.
- Change project ownership.
- Manage credits (create, transfer, cancel, expire).
- Query balances, statements, and transaction audits.
Responses
All client methods return PortalResponse
PrerequisitesΒΆ
-
Initialize the SDK and obtain the client.
using AIForged.API; var baseUrl = Environment.GetEnvironmentVariable("AIFORGED_BASE_URL") ?? "https://portal.aiforged.com"; var apiKey = Environment.GetEnvironmentVariable("AIFORGED_API_KEY") ?? throw new Exception("AIFORGED_API_KEY not set."); var cfg = new Config { BaseUrl = baseUrl, Timeout = TimeSpan.FromMinutes(5) }; await cfg.Init(); cfg.HttpClient.DefaultRequestHeaders.Add("X-Api-Key", apiKey); var ctx = new Context(cfg); var projects = ctx.ProjectClient;
Services within projects
ProjectViewModel.Services returns the services for the project as ParameterDefViewModel items. See the ParamDefClient documentation for service model details.
MethodsΒΆ
Get projects and services for a userΒΆ
Signatures
Task<PortalResponse<ObservableCollection<ProjectViewModel>>> GetByUserAsync(string userId, bool? includeBalance);
Task<PortalResponse<ObservableCollection<ProjectViewModel>>> GetByUserAsync(string userId, bool? includeBalance, CancellationToken cancellationToken);
Example
var resp = await projects.GetByUserAsync(userId: "user-123", includeBalance: true);
var userProjects = resp.Result;
Get a specific project for a userΒΆ
Signatures
Task<PortalResponse<ProjectViewModel>> GetUserProjectAsync(string userId, int? projectId);
Task<PortalResponse<ProjectViewModel>> GetUserProjectAsync(string userId, int? projectId, CancellationToken cancellationToken);
Example
var prj = await projects.GetUserProjectAsync(userId: "user-123", projectId: 1001);
var project = prj.Result;
Find a project by name for a userΒΆ
Signatures
Task<PortalResponse<ProjectViewModel>> GetByNameAsync(string userId, string projectName);
Task<PortalResponse<ProjectViewModel>> GetByNameAsync(string userId, string projectName, CancellationToken cancellationToken);
Example
var prj = await projects.GetByNameAsync(userId: "user-123", projectName: "Acme-Invoices");
var project = prj.Result;
Create a new projectΒΆ
Signatures
Task<PortalResponse<ProjectViewModel>> CreateAsync(int? groupId, ProjectViewModel project);
Task<PortalResponse<ProjectViewModel>> CreateAsync(int? groupId, ProjectViewModel project, CancellationToken cancellationToken);
Example
var newProject = new ProjectViewModel
{
Name = "Acme-Invoices",
Description = "Invoice processing agent",
Comment = "Initial setup",
Status = ProjectStatus.Active
};
var created = await projects.CreateAsync(groupId: null, project: newProject);
var project = created.Result;
Validation
Name, Description, and Comment have string length attributes in ProjectViewModel. Ensure values comply.
Update a projectΒΆ
Signatures
Task<PortalResponse<ProjectViewModel>> UpdateAsync(string userId, ProjectViewModel project);
Task<PortalResponse<ProjectViewModel>> UpdateAsync(string userId, ProjectViewModel project, CancellationToken cancellationToken);
Example
project.Description = "Updated description";
var updated = await projects.UpdateAsync(userId: "user-123", project: project);
var updatedProject = updated.Result;
Delete a projectΒΆ
Signatures
Task<PortalResponse<ProjectViewModel>> DeleteAsync(string userId, int? projectId);
Task<PortalResponse<ProjectViewModel>> DeleteAsync(string userId, int? projectId, CancellationToken cancellationToken);
Example
var deleted = await projects.DeleteAsync(userId: "admin-001", projectId: 1001);
var deletedProject = deleted.Result;
Get project service hierarchiesΒΆ
Signatures
Task<PortalResponse<ObservableCollection<ParameterDefViewModel>>> GetHierachiesAsync(
string userId, int? projectId, int? stpdId, int? groupId,
bool? includeCount, bool? onlyServices, bool? includeSettings, bool? includeChildren
);
Task<PortalResponse<ObservableCollection<ParameterDefViewModel>>> GetHierachiesAsync(
string userId, int? projectId, int? stpdId, int? groupId,
bool? includeCount, bool? onlyServices, bool? includeSettings, bool? includeChildren,
CancellationToken cancellationToken
);
Example
var hier = await projects.GetHierachiesAsync(
userId: "user-123",
projectId: 1001,
stpdId: null,
groupId: null,
includeCount: true,
onlyServices: false,
includeSettings: true,
includeChildren: true
);
var serviceTrees = hier.Result; // ParameterDefViewModel items
Scoping
Use stpdId to focus on a specific service. Set onlyServices to true to list services without field hierarchies.
List services for a projectΒΆ
Signatures
Task<PortalResponse<ObservableCollection<ParameterDefViewModel>>> GetServicesAsync(string userId, int? projectId, int? stlfilter, string enginefilter);
Task<PortalResponse<ObservableCollection<ParameterDefViewModel>>> GetServicesAsync(string userId, int? projectId, int? stlfilter, string enginefilter, CancellationToken cancellationToken);
Example
var svc = await projects.GetServicesAsync(userId: "user-123", projectId: 1001, stlfilter: null, enginefilter: null);
var services = svc.Result;
Change project ownerΒΆ
Signatures
Task<PortalResponse<bool>> ChangeOwnerAsync(string userId, int? projectId, string toUserId);
Task<PortalResponse<bool>> ChangeOwnerAsync(string userId, int? projectId, string toUserId, CancellationToken cancellationToken);
Example
var changed = await projects.ChangeOwnerAsync(userId: "admin-001", projectId: 1001, toUserId: "user-789");
var success = changed.Result;
Ownership changes
Ownership changes are impactful. Confirm projectId and toUserId before proceeding.
Credits: get available creditsΒΆ
Signatures
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetAvailableCreditsAsync(
string userId, int? projectId, DateTime? fromDate, DateTime? toDate, decimal? amount
);
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetAvailableCreditsAsync(
string userId, int? projectId, DateTime? fromDate, DateTime? toDate, decimal? amount, CancellationToken cancellationToken
);
Example
var credits = await projects.GetAvailableCreditsAsync(
userId: "auditor-1",
projectId: 1001,
fromDate: DateTime.UtcNow.AddMonths(-1),
toDate: DateTime.UtcNow,
amount: null
);
var available = credits.Result;
Credits: create manual creditΒΆ
Signatures
Task<PortalResponse<TransactionsAuditViewModel>> CreateCreditAsync(string userId, int? projectId, int? bundleId, decimal? customAmount, string comment);
Task<PortalResponse<TransactionsAuditViewModel>> CreateCreditAsync(string userId, int? projectId, int? bundleId, decimal? customAmount, string comment, CancellationToken cancellationToken);
Example
var credit = await projects.CreateCreditAsync(
userId: "admin-001",
projectId: 1001,
bundleId: null,
customAmount: 100m,
comment: "Manual credit for pilot"
);
var createdCredit = credit.Result;
Credits: transfer credits using an existing transactionΒΆ
Signatures
Task<PortalResponse<TransactionsAuditViewModel>> TransferCreditsAsync(
string userId, int? transactionId, int? projectId, int? bundleId, decimal? customAmount, string comment
);
Task<PortalResponse<TransactionsAuditViewModel>> TransferCreditsAsync(
string userId, int? transactionId, int? projectId, int? bundleId, decimal? customAmount, string comment, CancellationToken cancellationToken
);
Example
var transfer = await projects.TransferCreditsAsync(
userId: "admin-001",
transactionId: 555,
projectId: 2002,
bundleId: null,
customAmount: null,
comment: "Transfer remaining credits"
);
var transferred = transfer.Result;
Credits: transfer by amountΒΆ
Signatures
Task<PortalResponse<TransactionsAuditViewModel>> TransferCreditAmountAsync(
int? fromProjectId, int? debitServiceId, int? toProjectId, decimal? amount, string comment
);
Task<PortalResponse<TransactionsAuditViewModel>> TransferCreditAmountAsync(
int? fromProjectId, int? debitServiceId, int? toProjectId, decimal? amount, string comment, CancellationToken cancellationToken
);
Example
var moved = await projects.TransferCreditAmountAsync(
fromProjectId: 1001,
debitServiceId: null,
toProjectId: 2002,
amount: 250m,
comment: "Quarterly reallocation"
);
var moveResult = moved.Result;
Credits: cancel a creditΒΆ
Signatures
Task<PortalResponse<TransactionsAuditViewModel>> CancelCreditAsync(string userId, int? transactionId, string comment);
Task<PortalResponse<TransactionsAuditViewModel>> CancelCreditAsync(string userId, int? transactionId, string comment, CancellationToken cancellationToken);
Example
var canceled = await projects.CancelCreditAsync(
userId: "admin-001",
transactionId: 777,
comment: "Duplicate credit reversal"
);
var cancelResult = canceled.Result;
Credits: expire credits in a date rangeΒΆ
Signatures
Task<PortalResponse<TransactionsAuditViewModel>> ExpireCreditsAsync(string userId, int? projectId, DateTime? fromDate, DateTime? toDate, string comment);
Task<PortalResponse<TransactionsAuditViewModel>> ExpireCreditsAsync(string userId, int? projectId, DateTime? fromDate, DateTime? toDate, string comment, CancellationToken cancellationToken);
Example
var expired = await projects.ExpireCreditsAsync(
userId: "admin-001",
projectId: 1001,
fromDate: DateTime.UtcNow.AddMonths(-6),
toDate: DateTime.UtcNow,
comment: "Expire stale credits"
);
var expireResult = expired.Result;
Transaction audit (current)ΒΆ
Signatures
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetTransactionAuditAsync(
int? projectId, int? stpdId, DateTime? fromDate, DateTime? toDate, TimeSpan? interval, int? relatedTxId, bool? includeRelated
);
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetTransactionAuditAsync(
int? projectId, int? stpdId, DateTime? fromDate, DateTime? toDate, TimeSpan? interval, int? relatedTxId, bool? includeRelated, CancellationToken cancellationToken
);
Example
var audit = await projects.GetTransactionAuditAsync(
projectId: 1001,
stpdId: null,
fromDate: DateTime.UtcNow.AddDays(-30),
toDate: DateTime.UtcNow,
interval: TimeSpan.FromDays(1),
relatedTxId: null,
includeRelated: true
);
var transactions = audit.Result;
Related transactions
Use relatedTxId and includeRelated to explore linkages between credits, transfers, and charges.
Transaction audit (obsolete)ΒΆ
Signatures
[Obsolete]
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetAuditAsync(
int? projectId, int? stpdId, DateTime? fromDate, DateTime? toDate, TimeSpan? interval
);
[Obsolete]
Task<PortalResponse<ObservableCollection<TransactionsAuditViewModel>>> GetAuditAsync(
int? projectId, int? stpdId, DateTime? fromDate, DateTime? toDate, TimeSpan? interval, CancellationToken cancellationToken
);
Deprecated
Use GetTransactionAuditAsync instead of GetAuditAsync.
Get project balanceΒΆ
Signatures
Task<PortalResponse<decimal?>> GetBalanceAsync(string userId, int? projectId, int? stpdId, DateTime? effectiveDate);
Task<PortalResponse<decimal?>> GetBalanceAsync(string userId, int? projectId, int? stpdId, DateTime? effectiveDate, CancellationToken cancellationToken);
Example
var balanceResp = await projects.GetBalanceAsync(userId: "user-123", projectId: 1001, stpdId: null, effectiveDate: DateTime.UtcNow);
var balance = balanceResp.Result;
Get balances for multiple projectsΒΆ
Signatures
Task<PortalResponse<ObservableCollection<AccountBalanceItem>>> GetBalancesAsync(
string userId, int? projectId, int? stpdId, int? groupId, bool? allRelated, DateTime? fromDate, DateTime? toDate
);
Task<PortalResponse<ObservableCollection<AccountBalanceItem>>> GetBalancesAsync(
string userId, int? projectId, int? stpdId, int? groupId, bool? allRelated, DateTime? fromDate, DateTime? toDate, CancellationToken cancellationToken
);
Example
var balances = await projects.GetBalancesAsync(
userId: "user-123",
projectId: null,
stpdId: null,
groupId: null,
allRelated: true,
fromDate: DateTime.UtcNow.AddMonths(-3),
toDate: DateTime.UtcNow
);
var items = balances.Result;
Get statementΒΆ
Signatures
Task<PortalResponse<ObservableCollection<AccountBalanceItem>>> GetStatementAsync(
string userId, int? projectId, int? stpdId, int? groupId, DateTime? fromDate, DateTime? toDate, bool? allRelated, TimeSpan? interval
);
Task<PortalResponse<ObservableCollection<AccountBalanceItem>>> GetStatementAsync(
string userId, int? projectId, int? stpdId, int? groupId, DateTime? fromDate, DateTime? toDate, bool? allRelated, TimeSpan? interval, CancellationToken cancellationToken
);
Example
var stmt = await projects.GetStatementAsync(
userId: "user-123",
projectId: 1001,
stpdId: null,
groupId: null,
fromDate: DateTime.UtcNow.AddMonths(-1),
toDate: DateTime.UtcNow,
allRelated: false,
interval: TimeSpan.FromDays(1)
);
var statement = stmt.Result;
ModelsΒΆ
ProjectViewModelΒΆ
| Property | Type | Validation |
|---|---|---|
| Id | int | |
| UserId | string | |
| Status | ProjectStatus | |
| Name | string | StringLength(256) |
| Description | string | StringLength(450) |
| Comment | string | StringLength(450) |
| Dtc | DateTime | |
| Dtm | DateTime | |
| Balance | AccountBalanceItem | |
| TotalDocsCount | int? | |
| Services | ObservableCollection |
Timestamps
Dtc and Dtm are timestamps for creation and modification respectively.
AccountBalanceItemΒΆ
| Property | Type | Validation |
|---|---|---|
| Id | Guid | |
| Seq | int | |
| ServiceId | int? | |
| ServiceTypeId | int? | |
| ProjectId | int? | |
| GroupId | int? | |
| BundleId | int? | |
| IsTransfer | bool? | |
| UserId | string | |
| DT | DateTime? | |
| Info | string | |
| DRCount | decimal? | |
| CRCount | decimal? | |
| DRQty | decimal? | |
| CRQty | decimal? | |
| CRQry | decimal? | |
| DR | decimal? | |
| CR | decimal? | |
| Balance | decimal? | |
| Project | string | |
| Service | string | |
| ServiceType | string | |
| Bundle | string | |
| Name | string | |
| UserName | string | |
| TxIds | ObservableCollection |
TransactionsAuditViewModelΒΆ
| Property | Type | Validation |
|---|---|---|
| Id | int | |
| ProjectId | int | |
| ServiceId | int? | |
| DocumentId | int? | |
| BundleId | int? | |
| PaymentId | int? | |
| ChargeId | int? | |
| RelatedTxnId | int? | |
| Status | TransactionStatus | |
| UserId | string | StringLength(450) |
| RunId | string | StringLength(256) |
| DTC | DateTime | |
| DTM | DateTime | |
| Qty | int | |
| Price | double | |
| Cost | decimal | |
| Charge | decimal? | |
| IsCredit | bool | |
| CreditBalance | decimal? | |
| Comment | string | StringLength(128) |
| ExternalId | string | StringLength(64) |
| ProjectName | string | |
| IsBillingProject | bool | |
| ServiceName | string | |
| BundleName | string | |
| UserName | string | |
| AuditUserName | string |
EnumsΒΆ
ProjectStatusΒΆ
| Value | Numeric Value |
|---|---|
| None | 0 |
| Active | 1 |
| Disabled | 2 |
| Billing | 3 |
| Deleted | 90 |
| Error | 99 |
TransactionStatusΒΆ
| Value | Numeric Value |
|---|---|
| Active | 0 |
| Transfered | 1 |
| Deleted | 99 |
ExamplesΒΆ
Create, update, and fetch services for a projectΒΆ
// Create
var createResp = await projects.CreateAsync(groupId: null, project: new ProjectViewModel
{
Name = "Acme-Invoices",
Description = "Invoice processing agent",
Status = ProjectStatus.Active
});
var project = createResp.Result;
// Update
project.Comment = "Pilot rollout";
var updateResp = await projects.UpdateAsync(userId: "user-123", project: project);
var updated = updateResp.Result;
// List services
var services = (await projects.GetServicesAsync("user-123", updated.Id, stlfilter: null, enginefilter: null)).Result;
Credits lifecycle: create, transfer, cancelΒΆ
// Create a manual credit
var createdCredit = (await projects.CreateCreditAsync("admin-001", 1001, bundleId: null, customAmount: 150m, comment: "Kickoff credit")).Result;
// Transfer by amount to another project
var transferred = (await projects.TransferCreditAmountAsync(fromProjectId: 1001, debitServiceId: null, toProjectId: 2002, amount: 50m, comment: "Rebalance")).Result;
// Cancel a credit transaction
var canceled = (await projects.CancelCreditAsync("admin-001", transactionId: createdCredit.Id, comment: "Reversal")).Result;
Audit linkage
Use GetTransactionAuditAsync with relatedTxId to follow chains of transactions (original credit, transfers, cancellations).
Financial overview: balances and statementsΒΆ
// Single project balance
var balance = (await projects.GetBalanceAsync("user-123", projectId: 1001, stpdId: null, effectiveDate: DateTime.UtcNow)).Result;
// Multiple balances (last quarter)
var balances = (await projects.GetBalancesAsync("user-123", projectId: null, stpdId: null, groupId: null, allRelated: true, fromDate: DateTime.UtcNow.AddMonths(-3), toDate: DateTime.UtcNow)).Result;
// Statement aggregated by day
var statement = (await projects.GetStatementAsync("user-123", 1001, stpdId: null, groupId: null, fromDate: DateTime.UtcNow.AddMonths(-1), toDate: DateTime.UtcNow, allRelated: false, interval: TimeSpan.FromDays(1))).Result;
Service hierarchy visualizationΒΆ
flowchart TD
A["GetHierachiesAsync"] --> B["ParameterDefViewModel trees"]
B --> C["Include settings"]
B --> D["Include children"]
B --> E["Include counts"]
Pull service hierarchies
Set includeSettings and includeChildren to true to obtain full service trees for inspection or export.
TroubleshootingΒΆ
- Project not found
- Verify userId and projectId or use GetByNameAsync to lookup by name.
- Ownership change fails
- Confirm both userId and toUserId exist and have appropriate permissions.
- Credits operations unexpected
- Check date ranges and amounts; review GetTransactionAuditAsync to verify effective transactions.
- Empty services listing
- Confirm project is Active and user has access; try GetHierachiesAsync with onlyServices set to true.