Skip to content

API & Architecture

Verified against source (19)

  • Config/CustomRoutes.config
  • Config/Abstract.config
  • application/QboRouteHandler.cs
  • application/HttpAsyncHandler.cs
  • application/AbstractObject.cs
  • application/GenericObject.cs
  • application/CreateObject.cs
  • application/Enumerations.cs
  • application/Schedule.cs
  • Configuration/SqlPattern.cs
  • Configuration/CustomRoute.cs
  • Configuration/DbAttributes.cs
  • Interfaces/IQueue.cs
  • Interfaces/IService.cs
  • Interfaces/IMethodListener.cs
  • Services/Recipe.cs
  • application/HealthCheckHandler.cs
  • src/objectqueue
  • qbo.Queue.Amazon/SimpleQueue.cs

Every QBO module is a class (Contact, Process, Attachment, Decision, …) that derives from AbstractObject. Its operations are C# methods, SQL statements defined in its configuration, or configured services. All of them are reachable through the same routes.

Route Runs Example
/api/{module}/{operation} Synchronously on the web server /api/contact/search?LastName=Smith
/api/{module}/{operation}/{id} Synchronously, with ID={id} /api/contact/summary/1001
/api/{module}/{id} GET → Summary, DELETE → Delete, other verbs → Save /api/contact/1001
/api/{module}/queue/{operation} Queued for an app server /api/attachment/queue/generate?Template=Welcome Letter&Object=Contact&ObjectID=1001
/healthcheck Returns the installed version

A parent-scoped form, /api/{Object}/{ObjectID}/{module}/{operation}, is shorthand for passing Object and ObjectID. For example, /api/attachment/search?Object=Process&ObjectID=2002 lists a case’s documents.

Parameters can be sent on the query string or in the body as form-encoded, XML, or JSON. Send sensitive values (SSNs, account numbers) in the body so they stay out of URLs and logs. Authenticate with an X-ApiKey header (see Security).

Set Output=Xml|Json|JsonP|Xhtml|Html|Csv, or send an Accept header (application/json, text/xml, text/csv).

Use /api/{module}/{operation} for interactive calls. Use /api/{module}/queue/{operation} for long-running work, batches, document generation, third-party calls that need throttling or retries, and anything scheduled. The queued call returns immediately with a confirmation (Output=Xml shown):

<QueueMessageItem>
<Queue>DefaultQueue</Queue>
<MessageID>…</MessageID>
</QueueMessageItem>

Scheduled messages also include a ScheduleID.

Parameter Purpose
QueueName Target queue. Defaults to the queue configured for the operation, then DefaultQueue.
QueuedDate Run at a future time. The message waits in the future queue until then.
ScheduleName Run on a recurring schedule, such as Daily at 6am. QBO re-queues after each run.
ScheduleLabel A unique name for the schedule when the same operation needs different schedules.
QueueLabel A custom label for the queued item (when custom labels are enabled).
POST /api/organization/queue/listen
?Listeners=Nightly Sync
&ScheduleName=Daily at 5:00am
&ScheduleLabel=Organization Nightly Sync 5am

Test schedule text before using it:

GET /api/schedule/parse?ScheduleName=Monthly on the 2nd Sun every 2 months @ 6am&Output=Xml

Every module inherits these from AbstractObject and the shared Abstract.config:

Operation Purpose
Save Insert or update: with an ID it updates, without one it inserts (applying template rules).
Search Paged search with {Extranet.Default} row-level security applied.
SmartSearch Free-text search across configured search terms.
Select Read one record by ID.
Summary A record plus its significant children (what summary pages render).
Delete / BulkDelete Delete records.
BulkUpdate Update the columns you pass on many records (ID list).
ListByParent Children of a parent record.
ObjectTree All related Object / ID pairs.
Dashboard / Pivot Aggregates by dimension.
GrantAccess / RevokeAccess Manage group access to records.
Listen Run the module’s data listeners (all, or those named in Listeners) for changes since From or the last scheduled run.
SelectByTemplate Find the existing templated record that the template’s repeatability says to reuse.

Each operation is guarded by a permission named {Module}{Operation}, such as ContactSearch.

Parameter Purpose
any column name Matches that column, for example LastName=Smith.
SqlFilters Comma-separated named filters from the module’s configuration, for example SqlFilters=Active.
OrderBy Sort column; prefix with - for descending (OrderBy=-CreatedDate).
DisplaySize / RecordStart Paging.

Save behaves like PATCH. Properties you omit are left alone; a property sent with an empty value is set to null.

POST /api/contact/save?ID=1001&FirstName=Jane&MiddleName=&LastName=Doe

Related data saves in the same call:

  • Parent record: {Object}_{Field}, for example Organization_Organization=Acme Lending. Use with Object=Organization and no ObjectID to create the parent.
  • Nested collections: {Object}_{Collection}_{index}_{Field}, for example Organization_Contacts_0_Email=ada@acme.example.
  • Templates: Template or TemplateID applies the template’s defaults and repeatability (see Templates).

Use Output=Xml when you need new IDs back; JSON output omits a record’s data fields.

Extension point What it is
Statement A SQL statement in a module’s configuration. Available as an operation with its own permission, and can use {Extranet.*} for row-level security.
Extension method A C# extension method on a module class, decorated with [DbVoidMethod] (or another DbMethod attribute).
IService A plugin operation. Built-ins include RestApiService (REST calls), SqlService, ImportService, and Recipe (a series of operations with parameter substitution between steps).
IMethodListener Fires when named operations run; QueueListener queues the follow-up instead of running it inline.
IQueue A queue implementation: Amazon SQS, SQL Server Service Broker, and QBO’s own future, failure, and callback queues.
IFileObject / IGenerator Document storage and generation plugins (see Document Management).
Custom route A URL mapped to an operation, with optional Handler (IQboHttpHandler) and ExceptionHandler.

Configuration is stored as configuration entries (Source, ConfigurationType, ConfigurationKey, ConfigurationXml) and shipped as setup packages (Setup.{Name}.xml), so changes promote between environments as data.

An operation that starts external work, such as ordering a report from a vendor, can be marked [DbVoidMethod(Async = true)]. Workflow and imports then wait for a matching End{Operation} call instead of completing immediately. When the vendor delivers, the delivery operation calls EndInvokeAsync("End{Operation}", …), and the waiting workflow step or import continues.

[DbVoidMethod(Async = true)]
public static async Task WidgetOrderAsync(this ContactObject contact, IDictionary<string, object> parameters)
{
// place the order with the vendor
}
[DbVoidMethod(Async = true)]
public static async Task WidgetDeliveryAsync(this ContactObject contact, IDictionary<string, object> parameters)
{
// save the results, then release anything waiting on the order
await contact.EndInvokeAsync("EndWidgetOrder", "".ToProperties());
}
[DbVoidMethod]
public static Task EndWidgetOrderAsync(this ContactObject contact, IDictionary<string, object> parameters)
=> Task.CompletedTask;