Skip to content
flowon.com

Logic API

Calling the API

Build the address of any Logic API endpoint, authenticate, and send requests for records, queries, process actions, files and option sets.

This page is for the developers who call a published Logic API from a web app, a mobile app or another system. Every endpoint is a plain HTTP call that sends and receives JSON, so any HTTP client works. Share it with your app team together with the API’s OpenAPI schema.

The base address is wherever your organization hosts the API, for example https://api.contoso.com. Logic API adds no prefix of its own; if the host uses a base path (such as /portal), put it in front of every address below.

The address also determines which version of the API you call: each address serves one version. Ask the API owner for the address of each version.

Callers authenticate the way the API host requires, typically with a bearer token from your identity provider in the Authorization header:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi...

Endpoints that allow anonymous callers need no token. Endpoints that need a signed-in caller or a role answer 401 with UNAUTHORIZAD_ACCESS when the token is missing or doesn’t grant access. Ask the API owner which endpoints need what; see Access control.

All addresses are lowercase. {module}, {action} and {query} are the names given in API Studio; {entity} is the Dataverse logical name of the table (for example account, contact, incident); {id} is a record’s unique identifier.

Endpoint Method Address Request body
Read a record GET /{module}/{entity}/{id}/{action} —
Create a record POST /{module}/{entity}/{action} JSON inputs
Update a record PUT /{module}/{entity}/{id}/{action} JSON inputs
Delete a record DELETE /{module}/{entity}/{id}/{action} —
Upload a file POST /{module}/{entity}/{id}/{action} multipart/form-data, field file
Download a file GET /{module}/{entity}/{id}/{action}/{attachmentId} —
Run a process on a record POST /{module}/{entity}/{action}?id={id} JSON inputs
Run a module process POST /{module}/{action} JSON inputs
Run a query GET /{module}/{query}?{inputs} —
Global option set GET /optionsets/{name} —
Entity option set GET /{module}/{entity}/optionsets/{name} —

The examples use a customer-service API with modules service and sales.

POST /service/incident/submit
Authorization: Bearer eyJ0eXAiOi...
Content-Type: application/json
{
"title": "Router drops connection every evening",
"description": "Since the firmware update on 18 October the router restarts around 19:00.",
"prioritycode": 1
}
HTTP/1.1 200 OK
Content-Type: application/json
{ "id": "3f2a9c1e-5b7d-4e8a-9f10-2c3d4e5f6a7b" }
GET /service/incident/3f2a9c1e-5b7d-4e8a-9f10-2c3d4e5f6a7b/get
Authorization: Bearer eyJ0eXAiOi...
{
"ticketnumber": "CAS-01842-K9T2",
"title": "Router drops connection every evening",
"prioritycode": 1,
"customerid": { "id": "6b1f0c3e-2d4a-4b5c-8e9f-0a1b2c3d4e5f", "name": "Alpine Ski House" },
"attachments": [
{
"id": "c0a8e2f4-1b3d-4c5e-9f7a-8b6c4d2e0f1a",
"attachmentName": "Router log",
"contentType": "text/plain",
"fileName": "router-2026-10-21.log"
}
]
}

The fields returned are the ones chosen for the read action. Lookups come back as an object with id and name. attachments is present only when the action retrieves the attachment list.

Terminal window
curl -X POST "https://api.contoso.com/service/incident/3f2a9c1e-5b7d-4e8a-9f10-2c3d4e5f6a7b/attach" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@router-2026-10-21.log"
Terminal window
curl -o router.log \
"https://api.contoso.com/service/incident/3f2a9c1e-5b7d-4e8a-9f10-2c3d4e5f6a7b/file/c0a8e2f4-1b3d-4c5e-9f7a-8b6c4d2e0f1a" \
-H "Authorization: Bearer $TOKEN"

Upload one file per call. The download returns the file with its content type and file name.

GET /sales/accountsbycity?city=Seattle
Authorization: Bearer eyJ0eXAiOi...

Query inputs go on the query string. What comes back depends on the query’s multiplicity:

Multiplicity Response
Single One JSON object, or 204 No Content when nothing matches.
All A JSON array ([] when nothing matches).
Sliced A page object (see below).

Sliced queries accept page (the page number, starting at 1), page-size (records per page) and cursor (the value returned with the previous page). With page but no page-size, pages hold 20 records; with page-size but no page, you get page 1. Without either, you get the first page at Dataverse’s default page size (typically 5,000 records). Always send both for predictable paging:

GET /service/opencases?customerId=6b1f0c3e-2d4a-4b5c-8e9f-0a1b2c3d4e5f&page=1&page-size=20
{
"cursor": "…",
"count": 20,
"totalRecordCount": 47,
"hasMoreRecords": true,
"data": [ { "ticketnumber": "CAS-01842-K9T2", "title": "Router drops connection every evening" } ]
}
Field Meaning
data The records on this page.
count The number of records on this page.
totalRecordCount The total number of matching records.
hasMoreRecords true when there is another page.
cursor Pass it back with the next request to continue where this page ended. Treat it as an opaque value.

To read every page, repeat the request with the next page and the returned cursor until hasMoreRecords is false.

GET /optionsets/casetype?lcid=1036
[
{ "name": "Question", "value": 1 },
{ "name": "Problème", "value": 2 },
{ "name": "Demande", "value": 3 }
]

lcid picks the label language (for example 1033 English, 1036 French, 1031 German). Without it, labels are in English (1033). When a label doesn’t exist in the requested language, another available label is returned. Send the value, not the label, when an input expects a choice.

  • Load option sets once and cache them in the app; they change rarely.
  • Use the record id returned by a create call to read, update or attach files to the record.
  • Always check the HTTP status before reading the body; see Responses and errors.