Skip to content

Reuse one API call across workflows, documents, and pages

Verified against source (14)

  • application/AbstractObject.cs
  • application/AbstractCollection.cs
  • application/GenericObject.cs
  • Services/SqlService.cs
  • Properties/Settings.settings
  • Configuration/Service.Edit.xslt
  • decision/DecisionStep.cs
  • Decision/DecisionStepTemplate.Edit.xslt
  • process/Process.Fields.cs
  • Config/Organization.config
  • Config/Setup.DecisionChild.xml
  • Scripts/qbo3.js
  • qbo4.Common/RegexPattern.cs
  • Extensions/MatcherContainerExtensions.cs

Every screen in QBO is built on API calls, so anything a user can do, a workflow, template, import, or script can do too. In this walkthrough you take one operation, such as a query that returns account details from another system, and reuse it in three places: a workflow step that saves the results to QBO records, a form that keeps the fields QBO has no column for, and a page script that shows the data live. Define the call once, and every building block can use it.

Who it’s for: power users and developers who configure workflows, templates, and screens.

Prerequisites

  • Permission to edit workflow templates, and to add statements or services to a module (Configuration > Modules).
  • An operation to reuse. This can be a standard operation (Search, Save, Summary), a SQL statement you add to a module, or a service that calls another system. Launch workflows from a data warehouse query shows how to add one that queries an external database.

An operation is written as a method signature: {Module}/{Operation}?{parameters}, such as Contact/Search?LastName=Smith. The same signature works in all of these places:

Building block Setting What the call does there
Workflow Advanced step Data Source and Action Fetches rows, then calls another operation once for each row.
Documents Document template Data Fetches the data merged into a Word or PDF template.
Messaging Message template Data Fetches the data merged into an email or text.
Imports Import Files > Batch Apply Runs a query and queues an operation for every row, with an audit trail.
Scoring Score template Method Supplies the data a score engine calculates from.
Ledgers Ledger template Calculate method / Project method Replaces the standard calculation with your own statement.
Worklists Worklist template Calculate method Selects the records that belong in a query-based worklist.
Pages A script in a form layout or custom view Calls the operation from the browser and uses the JSON or HTML it returns.

From outside QBO, the same operation is /api/{module}/{operation}. For example, Contact/Search?LastName=Smith becomes GET /api/contact/search?LastName=Smith. See API & Architecture for authentication and queued execution.

Call the operation directly and look at the columns it returns. These column names are what you’ll map in the next steps.

GET /api/contact/customerupdates?Output=Json

CustomerUpdates here is an example statement or service on the Contact module that returns recently changed customers from a data warehouse, with the columns Id, First, and Last.

In a workflow template, add an Advanced Step:

  1. Name the step, for example Sync customers.

  2. For Data Source, choose Operation, then select the module (Contact) and operation (CustomerUpdates). Leave Batch checked to track each row.

  3. For Action, select Contact and Save, and enter the parameters:

    FirstName={First}&LastName={Last}&SubscriberID=datalake.acme.example-Customer-{Id}
  4. Choose Async so the step runs on an app server, and save.

When the step runs, QBO calls Contact/Save once for each row, replacing each {Column} placeholder with that row’s value:

Source column Saved as
First FirstName
Last LastName
Id part of the SubscriberID

SubscriberID is a key you make up that stays the same for the same source record. The first run creates each contact and registers the key; later runs find the contact by its key and update it instead of creating a duplicate. A pattern of {source system}-{table}-{key} keeps keys unique across systems.

Source systems often have fields that don’t match a QBO column. Store those as answers on a form (task) attached to the record. Suppose a Process/AccountDetail operation returns Account, Client, Adjuster, ClaimAmount, and ClaimDetail:

  1. Create a task template named Snapshot that applies to processes. Set Repeatable to One per parent so each run updates the same snapshot instead of adding another.

  2. In an advanced step, set Data Source to Process / AccountDetail and Action to Process / Save with:

    Process={Account}&Client_Organization={Client}&Vendor_Organization={Adjuster}&{Forms_Snapshot_*}

Each part does one job:

Parameter Effect
Process={Account} Names the process after the account.
Client_Organization={Client} Sets the process’s client to the organization with that name. A prefix that matches a related record (Client_, Vendor_) saves to that record, so QBO finds the organization by name or creates it.
Vendor_Organization={Adjuster} Does the same for the vendor.
{Forms_Snapshot_*} Copies every column of the row to the Snapshot task as answers.

{Forms_Snapshot_*} is shorthand for listing each column yourself:

Forms_Snapshot_Account={Account}&Forms_Snapshot_Client={Client}&Forms_Snapshot_Adjuster={Adjuster}&Forms_Snapshot_ClaimAmount={ClaimAmount}&Forms_Snapshot_ClaimDetail={ClaimDetail}

Forms is the record’s collection of tasks, Snapshot picks the task template by name (with spaces removed, so Account Snapshot becomes AccountSnapshot), and * expands to every column the query returned. A plain {*} expands to every column with no prefix.

In a customizable view, such as a form’s layout, a script can call the same operation from the browser. To get the data as JSON:

var accountDetail = {};
new qbo3.ProcessObject().invokeJson(
'AccountDetail',
{ }, // parameters AccountDetail needs go here
function (json) { accountDetail = json; }
);

Use the result to fill in fields, validate an answer, or show a warning.

To show the data instead, add a placeholder element and have QBO render the results into it:

<div id="accountDetail">Loading…</div>
new qbo3.ProcessObject({ target: 'accountDetail' }).invokeHtml(
'AccountDetail',
{ Transform: 'Templates/Report/Standard.xslt' }
);

The target option names the element to fill, and the Transform parameter renders the results as HTML. The standard transform shows every column in a table; write your own XSLT for any other layout.

One operation now does three jobs: a workflow step keeps QBO records in sync with the source system, a snapshot task holds the extra fields where workflows, worklists, and reports can use them without calling the source again, and a page shows live data. When the source changes, update the operation in one place and everything that uses it picks up the change.