This QuickStart demonstrates integrating ServiceNow's REST API with Sigma using Basic Authentication and API Actions—showing you how to build a complete bidirectional integration for incident management without ETL pipelines.
What you'll build:
A Sigma workbook that:
Along the way you'll learn how to:
For more information on Sigma's product release strategy, see Sigma product releases
If something doesn't work as expected, here's how to contact Sigma support
This QuickStart is designed for Sigma developers integrating external APIs, technical ServiceNow users building custom dashboards, and IT service management teams working across Sigma and ServiceNow workflows.

Before building the integration, you need a ServiceNow developer instance with sample incident data. ServiceNow provides free Personal Developer Instances (PDIs) for learning and testing.
We will demonstrate using the sample data provided in ServiceNow developer accounts.
If you don't already have a ServiceNow developer account:
Step 1: Navigate to the ServiceNow Developer Portal
Click Sign up (or Log in if you already have an account).
Step 2: Create an Account
Complete the registration form with your details. You'll receive a confirmation email.
Step 3: Request a Personal Developer Instance
Once logged in:
Request Instance (green button in the top right)Zurich (Latest release)RequestThe instance takes ~5-10 minutes to provision. You'll see a confirmation page with your instance details.
Step 4: View Instance Details
Once your instance is ready, you'll see:
https://devXXXXXX.service-now.com/ (where XXXXXX is your unique instance number)adminStep 5: Open Your Instance
Click on the Instance URL to open your ServiceNow instance in a new tab:

You'll be taken to the ServiceNow home page where you can open the All menu and select Incidents:

Step 6: Navigate to Incidents
Click on All to set the filters to show every incident:

Step 7: Inspect an Incident
Click on any incident number (like INC0009005) to open the incident form.
Verify you can see fields like:

We now have:
admin)https://devXXXXXX.service-now.com/)
Now that your ServiceNow instance is verified, let's configure authentication in Sigma. ServiceNow supports Basic Authentication using username and password, which is perfect for developer instances.
In Sigma, open the left navigation menu and select Administration > Credentials and click the Create credential button:

In the Create Credential dialog:
ServiceNow Basic AuthBasic Authenticationadmin (your ServiceNow admin username)devXXXXXX.service-now.com (replace with your actual instance domain)
Click Create to save the credential.
You'll see ServiceNow Basic Auth in your API Credentials list.
We now have:
For more information, see Add a new API credential to Sigma

Now we'll create an API connector that queries incidents from ServiceNow's Table API. This connector will use the Basic Auth credential we just created.
ServiceNow provides a REST API for accessing table data:
Endpoint: GET /api/now/table/{table_name}
For incidents: GET /api/now/table/incident
Query Parameters:
sysparm_limit: Number of records to returnsysparm_fields: Comma-separated list of fields to returnsysparm_query: Encoded query string for filteringDocumentation: ServiceNow Table API
Step 1: Navigate to API Connectors
In Sigma, navigate to Administration > API Connectors and click Create connector:

Step 2: Configure Base URL
Configure the new connector using:
ServiceNow - Get IncidentsServiceNow Basic Auth (the credential we created earlier)https://devXXXXXX.service-now.com/api/now/table/incidentdevXXXXXX with your actual instance numberhttps://dev555471.service-now.com/api/now/table/incident
Step 3: Add Query Parameters
In the Query Parameters section, click the + Add:
Parameter 1:
sysparm_limitStatic100This limits results to 100 incidents.
Parameter 2:
sysparm_fieldsStaticnumber,sys_id,short_description,state,priority,urgency,caller_id, opened_at,closed_at,assigned_toThe field list to return to Sigma in the response.
Parameter 3 (Dynamic):
sysparm_queryDynamicThis is a Dynamic filter for incident state, sent from Sigma at runtime:

Step 4: Test the Connector
Before saving, let's test the connector:

sysparm_query to: state=1Send Test RequestYou should see a JSON response with incident data in the Body section:

Step 5: Save the Connector
Click Create to save the connector.
You'll see ServiceNow - Get Incidents in your API Connectors list.
ServiceNow uses numeric codes for incident states:
State Code | State Name |
1 | New |
2 | In Progress |
3 | On Hold |
6 | Resolved |
7 | Closed |
8 | Canceled |
We'll use these codes when building filters in our workbook.
We now have:
sysparm_query parameter
Sigma's API Actions return raw JSON responses. To parse ServiceNow's response (a list of incidents) into an interactive table, we use a Sigma Python element.
Python elements execute on Snowflake, so we need to prepare your Snowflake environment.
In Snowflake, execute these commands as ACCOUNTADMIN:
USE ROLE ACCOUNTADMIN;
CREATE WAREHOUSE IF NOT EXISTS PYTHON_WH
WAREHOUSE_TYPE = STANDARD
WAREHOUSE_SIZE = XSMALL
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
COMMENT = 'Dedicated warehouse for Sigma Python queries';
ALTER WAREHOUSE PYTHON_WH RESUME;
GRANT USAGE ON WAREHOUSE PYTHON_WH TO ROLE SIGMA_SERVICE_ROLE;
GRANT CREATE PROCEDURE ON SCHEMA QUICKSTARTS.INPUT_TABLES_WRITE TO ROLE SIGMA_SERVICE_ROLE;
In Sigma, navigate to Administration > Connections.
Find your Snowflake connection and click to edit it:
PYTHON_WH
Click Save.
Now we need to initialize Snowflake's Python procedure. This is a one-time setup.
Create a test workbook:
Python element using the Element bar > Data > Python.import pandas as pd
sigma.output("test", pd.DataFrame({"status": ["initialized"]}))
RunYou'll see output indicating Python executed successfully:

There is no need to save this workbook.
Once the element executes successfully, return to Snowflake and run the following to grant access to the procedure:
USE ROLE ACCOUNTADMIN;
GRANT USAGE ON PROCEDURE QUICKSTARTS.INPUT_TABLES_WRITE.RUN_PYTHON_CODE(VARCHAR, VARCHAR) TO ROLE SIGMA_SERVICE_ROLE;
We now have:

Now we'll build a Sigma workbook that calls the ServiceNow API, parses the JSON response, and displays incidents in a table with dynamic filtering.
Step 1: Create a New Workbook
In Sigma, click Create New > Workbook.
Click Save as and name the workbook: ServiceNow API Actions QuickStart
Step 2: Add a Text Area Control for Raw Response
We'll use a text area control to store the raw JSON response from ServiceNow.
Element bar to add a Controls > Text AreaControl ID to: raw-responseLeave it blank (the API action will populate it):

Step 3: Add a List Control for State Filter
Create a control that lets users filter the loaded incidents by state:
Element bar to add a Controls > List valuesControl ID to: state-filterValue |
New |
In Progress |
On Hold |
Resolved |
Closed |

Be sure to disable Allow multiple selection as the value must contain one selection only:

TARGETS to the ServiceNow Incidents table and the State column
Step 4: Add a Button to Call the API
Create a button that triggers the API call:
Add > UI > ButtonLoad ServiceNow IncidentsStep 5: Configure the Button Action
Now we'll configure the button to call the ServiceNow API:
Actions menu+ to add an Action sequenceCall APIConfigure the first action:
Field | Value |
Action |
|
API Connector |
|
sysparm_query |
|

+ to add a second action to the sequenceSet control valueConfigure the second action:
Field | Value |
Action |
|
Update control |
|
Set value as |
|
Variable |
|

This stores the API response JSON in the text area control for parsing.
Step 6: Test the API Call
Click the Load ServiceNow Incidents button.
You should see the raw-response text area populate with JSON data from ServiceNow.

Now we'll use a Python element to transform the JSON response into a Sigma table.
Step 7: Add a Python Element
Python element using the Element bar > Data > Python.import pandas as pd
import json
# Fallback empty DataFrame with typed columns.
# Snowflake requires a defined schema even when there are no rows to display.
EMPTY = pd.DataFrame({
"Number": pd.Series(dtype="str"), "Sys ID": pd.Series(dtype="str"),
"Short Description": pd.Series(dtype="str"), "State": pd.Series(dtype="str"),
"Priority": pd.Series(dtype="str"), "Urgency": pd.Series(dtype="str"),
"Caller": pd.Series(dtype="str"), "Opened At": pd.Series(dtype="str"),
"Closed At": pd.Series(dtype="str"), "Assigned To": pd.Series(dtype="str")
})
# ServiceNow returns numeric codes for State, Priority, and Urgency.
# These maps convert them to readable labels for display in the table.
STATE = {"1":"New","2":"In Progress","3":"On Hold","6":"Resolved","7":"Closed","8":"Canceled"}
PRIORITY = {"1":"1 - Critical","2":"2 - High","3":"3 - Moderate","4":"4 - Low","5":"5 - Planning"}
URGENCY = {"1":"1 - High","2":"2 - Medium","3":"3 - Low"}
# Read the raw JSON response stored in the workbook text area control.
raw = sigma.get_control_value("raw-response")
try:
# Parse the JSON and extract the result array.
# If the response is an error or not a list (e.g. a PATCH response), default to empty.
incidents = json.loads(raw).get('result', [])
if not isinstance(incidents, list):
incidents = []
rows = []
for i in incidents:
# ServiceNow returns reference fields (caller, assigned_to) as nested objects.
# Extract the display_value when present, otherwise use the raw value.
caller = i.get('caller_id', '')
assigned = i.get('assigned_to', '')
if isinstance(caller, dict): caller = caller.get('display_value', '')
if isinstance(assigned, dict): assigned = assigned.get('display_value', '')
rows.append({
'Number': i.get('number',''), 'Sys ID': i.get('sys_id',''),
'Short Description': i.get('short_description',''),
'State': STATE.get(i.get('state',''), i.get('state','')),
'Priority': PRIORITY.get(i.get('priority',''), i.get('priority','')),
'Urgency': URGENCY.get(i.get('urgency',''), i.get('urgency','')),
'Caller': caller, 'Opened At': i.get('opened_at',''),
'Closed At': i.get('closed_at',''), 'Assigned To': assigned
})
# Build the DataFrame, or return the typed empty schema if no incidents matched.
df = pd.DataFrame(rows) if rows else EMPTY
except Exception:
# Return empty on any parse error (missing raw value, API error response, etc.)
df = EMPTY
# Output the DataFrame to Sigma as a named result set.
sigma.output("servicenow_incidents", df)
Step 8: Run the Python Element
Click Run (bottom right of the Python element).
You should see output indicating the Python executed successfully.

Step 10: Create a Table from Python Output
Create > Child Element > Table
You should now see a table populated with ServiceNow incident data:

Rename the table: ServiceNow Incidents.
Now return to the state-filter control and complete step 4 from earlier — set the TARGETS to the ServiceNow Incidents table and the State column.
Step 11: Add Python Action to the Load Button
Now that the Python element exists, we need to go back to the Load ServiceNow Incidents button and add a third action to run it after the raw response is stored:
Load ServiceNow Incidents button to select itActions panel, click + to add a third action to the existing sequenceRun Python element > Code (ServiceNow Incidents)
The button now has three actions in sequence: (1) Call the ServiceNow API, (2) Store the response in raw-response, (3) Run the Python element to parse and display the data.
Step 12: Test the State Filter
Click Load ServiceNow Incidents to load all incidents, then select a value from the State filter (e.g., In Progress).
The table should immediately filter to show only incidents matching the selected state. Use the x on the control to clear the filter and return to all incidents.
We now have:

Now we'll add the ability to update incident states in ServiceNow directly from Sigma. This demonstrates bidirectional integration—not just reading data, but writing changes back to the source system.
Step 1: Create a New API Connector
Navigate to Administration > API Connectors and click Create Connector.
Step 2: Configure the Update Connector
ServiceNow - Update IncidentUpdate Incident StateServiceNow Basic AuthPATCHhttps://devXXXXXX.service-now.com/api/now/table/incident/:sys_iddevXXXXXX with your instance number:sys_id is a path parameter that will be replaced at runtimeStep 3: Configure Path Parameter
Because the Base URL includes :sys_id, Sigma automatically creates the sys_id path parameter. You just need to change its mode:
In the Path Parameters section, find the auto-generated sys_id row and set the Mode to Dynamic:

The sys_id value will be passed at runtime from the workbook action.
Step 4: Configure Request Body
In the Body parameters section:
JSON{
"state": {{newState}}
}

Step 5: Define Body Variables
In the Body Variables section set the variable newState to use Number type.

Save the new connector.
Step 6: Test the Update Connector
Return to the ServiceNow Incidents table and copy a Sys ID value from one of the records that has a State of On Hold. We will use this as a test record, taking the incident from On Hold to In Progress.
With the Sys ID copied return to the ServiceNow - Update Incident API connector.
In the Test section:
Edit buttonTest connector linksysId to a real sys_id from your table (copy one from the Sys ID column)newState to: 2 (In Progress)TestYou should see a successful response with the updated incident data.

Save the connector.
We can verify that the state change was successful in ServiceNow as well by looking at the Activities section for the Incident Number tested:


Now we'll add UI elements to allow users to select an incident and update its state.
We'll use a modal to show a popup when users click an incident:
+ and select Add modal:
update-incident-modalUpdate Incident StateMight as well rename Page 1 to ServiceNow Incidents.
Inside the modal, add these controls:
Control 1: Incident Number
Controls > Text inputmodal-incident-numberIncident NumberControl 2: Current Description
Controls > Text inputmodal-descriptionDescriptionControl 3: Sys ID
Controls > Text inputmodal-sys-idSys IDControl 4: New State
Controls > List valuesmodal-new-stateSelect New StateDisplay Value | Actual Value |
In Progress | 2 |
On Hold | 3 |
Resolved | 6 |
Closed | 7 |

Be sure to disable the Allow multiple selection checkbox under the list select control. The API expects a single value for State:

Control 5: Button - Submit Update
We can just configure one of the default buttons instead of adding a new one. Let's configure Primary for this; click that button and set the label to Update Incident.
Also disable the Secondary button since we won't need that:

Now we can configure the ServiceNow Incidents table to open the modal when a row is clicked.
Return to the ServiceNow Incidents page.
We will configure an action on the Number column so that when a user clicks a specific incident number, the modal will open and allow them to set a new State.
Number column to select itActions > Add sequence > +Set Control ValueSet these control values:
Update control = Incident Number (update-incident-modal)Set value as = Column / NumberThis sends the selected Number to the modal and is shown on the modal-incident-number text input control.

Repeat the process for the other values we want to pass to the modal.
For example, the action configurations needed are for Description and Sys ID:

Add a fourth action to open the update-incident-modal:

Open the update-incident-modal page.
Configure the Update Incident button actions to call the ServiceNow - Update Incident API connector:
Actions menuAdd ActionCall APIConfigure the API action:
ServiceNow - Update Incidentsys_id: type = Control, value = Sys Id (update-incident-modal)newState: type = Formula, value = Number([modal-new-state])
Add Action (add a second action)Call APIConfigure the second action to re-fetch the updated incident list:
ServiceNow - Get IncidentsStatic value, value = "" (empty string — returns all incidents)
Add Action (add a third action)Set control valueConfigure the third action to store the fresh response:
raw-response (Controls)Action variableData (from Call ServiceNow - Get Incidents)
Add Action (add a fourth action)Run Python element > Code (ServiceNow Incidents): 
Add Action (add a fifth action)Close ModalStep 12: Test the Update Workflow
Return to the ServiceNow Incidents page.
Load ServiceNow Incidents button to load fresh dataNumber column and work with the first record...)
On Hold or In Progress as the new state — note the current state first so you can verify the changeUpdate IncidentThe modal should close, and the table should refresh showing the updated state.
For example, if we change INC0000001 from In Progress to On Hold in Sigma, we can see the result in Servicenow:

We now have:

In about an hour, you built a complete bidirectional ServiceNow integration—querying live incidents with dynamic state filters, parsing nested JSON responses with Python, and updating incident states directly in ServiceNow through an interactive modal—all without writing backend code or managing a single server.
What used to require a dedicated integration layer, ETL pipelines, and ongoing infrastructure maintenance is now a Sigma workbook. Sigma's API Actions handle the authentication, parameter passing, and response handling, so you can focus on the workflow rather than the plumbing.
The pattern you built here isn't limited to ServiceNow. Any SaaS platform with a REST API and Basic Authentication support—Zendesk, JIRA, GitHub, Freshservice, PagerDuty—can be integrated the same way. Query live data, surface it in Sigma, let users act on it, and write changes back. No middleware, no replication, no custom UI.
For IT and operations teams, this changes what's possible. Analysts who previously needed engineering support to build operational tooling can now do it themselves. Instead of exporting data to spreadsheets and manually updating systems, the workflow lives in Sigma—where the data already is.
Sigma isn't just a place to report on what happened. With API Actions, it becomes the place where your team takes action on what's happening right now.
Additional Resource Links
Blog
Community
Help Center
QuickStarts
Be sure to check out all the latest developments at Sigma's First Friday Feature page!
