incident, change_request, problem, task, users, groups, roles, locations, companies, and custom u_ tables from seed config, with encoded queries (sysparm_query), dot-walked fields, display values, and Link and X-Total-Count paging headers. Incidents, changes, and problems follow ServiceNow’s choice values, numbering, priority lookup, and state rules. Basic auth with seeded users, roles checked by ACL-like rules, and OAuth at /oauth_token.do work as on an instance, and the Attachment and Aggregate APIs cover the basics. ServiceNow has no widely used official Node SDK; the tests drive the emulator with raw HTTP through a thin typed client, as integrations do with fetch or axios.
At a glance
Start
--service. When it is the only enabled service, it listens on http://localhost:4000.
Without seed config, the instance has the user admin with password admin and the base roles admin, itil, itil_admin, user_admin, snc_read_only, and snc_internal.
Point your client’s instance URL at the emulator:
URL mapping
Auth
- Basic: a seeded user’s
user_nameandpassword. Every instance hasadminwith passwordadmin(sys_id6816f79cc0a8016401c5a33be04be441, roleadmin). User names match without regard to case. Inactive and locked out users cannot sign in. - Bearer: an OAuth access token from
/oauth_token.do, or a token the CLI accepts (for exampletest_token_admin), which acts as the user whoseuser_nameis the token’s login (adminby default).
{ "error": { "message": "User Not Authenticated", "detail": "Required to provide Auth information" }, "status": "failure" } with WWW-Authenticate: Basic realm="Service-now". Wrong credentials and unknown, revoked, or expired tokens answer 401 with User is not authenticated.
OAuth
POST /oauth_token.do takes a form body (or JSON) with client_id and client_secret (or HTTP Basic) from oauth.clients:
grant_type=passwordwithusernameandpasswordgrant_type=refresh_tokenwithrefresh_token; the answer carries a new access token and the same refresh tokengrant_type=authorization_codewithcode,redirect_uri, andcode_verifierwhen the authorize step sent a PKCE challenge (S256orplain)grant_type=client_credentialswhenoauth.client_credentialsis true and the client names aclient_credentials_user(no refresh token)
{ "access_token": "...", "refresh_token": "...", "scope": "useraccount", "token_type": "Bearer", "expires_in": 1799 }. Access tokens last 1800 seconds and refresh tokens 100 days unless the client sets access_token_lifespan and refresh_token_lifespan. A bad client, bad credentials, or a used or expired code answer 401 { "error_description": "access_denied", "error": "server_error" }, as an instance does; an unknown grant answers 400 unsupported_grant_type.
GET /oauth_auth.do?response_type=code&client_id=...&redirect_uri=...&state=... shows a sign-in page listing active users. Choosing one redirects to the redirect URL with code and state; declining sends error=access_denied. POST /oauth_revoke_token.do with the client credentials and token revokes it (a refresh token takes the user’s access tokens with it).
Table API
Every route is served at/api/now/table/{table}, /api/now/v1/table/{table}, and /api/now/v2/table/{table}.
Errors use ServiceNow’s body
{ "error": { "message", "detail" }, "status": "failure" }:
Values are strings. Unknown fields in a body are ignored, read only fields (
sys_*, number, computed fields) are ignored except sys_id and number on insert, booleans and numbers become strings, and a reference accepts a sys_id or a display value (user names too). Without sysparm_input_display_value, a choice label is stored as given, as GlideRecord does. Saving without a change keeps sys_mod_count.
Query parameters
References read as
{ "link": "<url>/api/now/table/sys_user/<sys_id>", "value": "<sys_id>" }, as { "display_value", "link" } with display values, and as { "display_value", "link", "value" } with all. An empty reference is "". Date/times are stored in UTC as yyyy-MM-dd HH:mm:ss and shown in the user’s time_zone (or the instance’s time_zone). Journal fields (comments, work_notes) read as ""; writing them adds a sys_journal_field entry, and their display value is the history, newest first.
Link holds first, prev (after the first page), next (when more rows follow), and last, keeping the other parameters. X-Total-Count counts matching rows before row ACLs, so a user who may not read every row can get a short page, as on an instance.
Encoded queries
Operators:
=, !=, >, >=, <, <=, LIKE, NOT LIKE (or NOTLIKE), STARTSWITH, ENDSWITH, IN, NOT IN, ISEMPTY, ISNOTEMPTY, ANYTHING, EMPTYSTRING, BETWEEN (low@high), ON and NOTON (Today@javascript:gs.beginningOfToday()@javascript:gs.endOfToday(), a label such as Last week, or a date), RELATIVEGT, RELATIVEGE, RELATIVELT, RELATIVELE, RELATIVEEE (@day@ago@3), SAMEAS, NSAMEAS, DYNAMIC (the “Me” filter 90d1921e5f510100a9ad2572f2b477fe), and INSTANCEOF on sys_class_name.
- Integers and choice fields such as
stateandprioritycompare as numbers, date/times as instants, booleans astrue/false, and strings without regard to case. - References match sys_ids with
=andIN, and their display values withLIKE,STARTSWITH,ENDSWITH, and with=when the value is not a sys_id. Dot-walk through them:caller_id.company.name=ACME. !=,NOT IN,NOT LIKE, andNOTONnever match empty values (add^ORfieldISEMPTY).field=matches empty values.javascript:values recognize the common GlideSystem helpers, worked out in the user’s time zone:gs.getUserID(),gs.getUserName(),gs.now(),gs.nowDateTime(),gs.beginningOf...()andgs.endOf...()for Today, Yesterday, Tomorrow, This, Last, and Next Week, Month, Quarter, and Year, and Last 15, 30, or 45 Minutes and Last Hour or 2 Hours,gs.daysAgo(n),gs.daysAgoStart(n),gs.daysAgoEnd(n)and the same for minutes, hours, months, quarters, and years, andgs.dateGenerate('2026-01-01','start'). Weeks start on Monday. Any other script matches no rows.- A condition on an unknown field or a term that is not a condition is dropped, as on an instance. With
invalid_query_returns_no_rows: true(theglide.invalid_query.returns_no_rowsproperty) such a query returns no rows.
Tables
Every row has
sys_id (32 hex characters), sys_created_on, sys_created_by, sys_updated_on, sys_updated_by, sys_mod_count, and sys_tags. Impact and urgency are 1 High, 2 Medium, 3 Low; priority is 1 Critical to 5 Planning.
Business rules
- Incident:
priorityfollows impact and urgency through the default priority lookup and cannot be set directly. Resolving (6) or closing (7) needsclose_codeandclose_notes(Resolution codeandResolution notes), then stampsresolved_atandresolved_by; closing also stampsclosed_atandclosed_by.activeis false when Closed or Canceled. Leaving Resolved countsreopen_countand clears the resolution stamps. Leaving On Hold clearshold_reason. Changing the assignment group countsreassignment_count.incident_statefollowsstate. - Change request: types
normal(default),standard, andemergencyfollow ServiceNow’s state models: normal New, Assess, Authorize, Scheduled, Implement, Review, Closed; emergency skips Assess; standard goes New, Scheduled, Implement, Review, Closed. Assess, Authorize, and Scheduled may go back to New, and any open state may be Canceled. Other moves answer 403Invalid state transition .... Scheduling a normal or emergency change needsapprovalapproved. Closing needsclose_code(successful,successful_issues,unsuccessful) andclose_notes. A planned end before the planned start is refused. - Problem:
priorityfollows impact and urgency. Resolving (106) or closing (107) needsresolution_code(fix_applied,risk_accepted,canceled,duplicate). Closed problems are inactive.
Access
adminpasses every check.snc_read_onlydenies every write, even for admin.- Task tables:
itilreads and writes; users without it read incidents they are the caller of or opened, and create incidents. Closed and canceled incidents, closed problems, and closed or canceled changes are read only except for admin. Only admin deletes task rows. - Users, groups, roles, and memberships: everyone reads;
user_adminwrites. Locations and companies: everyone reads; admin writes. - Journal entries and attachments are readable with the record they belong to.
- Custom tables:
read_roles(default: any signed in user) andwrite_roles(defaultitil). - Roles come from
sys_user_has_role, from groups throughsys_group_has_role, and from roles they contain (itil_admincontainsitil).
ACL Exception ... Failed due to security constraints.
Attachment API
POST /api/now/attachment/file?table_name=incident&table_sys_id=<sys_id>&file_name=log.txtwith the raw bytes and theirContent-TypePOST /api/now/attachment/uploadwith multipart form fieldstable_name,table_sys_id, and a file partGET /api/now/attachmentwithsysparm_query,sysparm_limit, andsysparm_offsetGET /api/now/attachment/{sys_id}for metadata (file_name,content_type,size_bytes,hash,table_name,table_sys_id,download_link, …)GET /api/now/attachment/{sys_id}/filefor the bytes, withX-Attachment-MetadataDELETE /api/now/attachment/{sys_id}
Aggregate API
GET /api/now/stats/{table} (also /api/now/v1/stats/{table}) takes sysparm_query, sysparm_count=true, sysparm_avg_fields, sysparm_sum_fields, sysparm_min_fields, sysparm_max_fields, sysparm_group_by (or GROUPBYfield in the query), sysparm_order_by (COUNT or COUNT^DESC), and sysparm_display_value. Without grouping it answers { "result": { "stats": { "count": "12", "avg": { ... } } } }; with grouping, { "result": [{ "stats": { "count": "3" }, "groupby_fields": [{ "field": "priority", "value": "1", "display_value": "1 - Critical" }] }] }.
Seed config
-
time_zone: users without their own time_zone see date/times here -
Custom tables and fields must start with
u_. Tables mayextendanother table (taskputs their rows in the task table and gives them task fields and rules). Fieldtypeis one ofstring(default),integer,decimal,boolean,glide_date_time,glide_date,reference(withreference),email,url,phone_number,glide_list, orjournal_input. -
recordsvalues are read as display values: choice labels, user names, and names of referenced rows work, and date/times are in the instance’s time zone. Business rules run, so a resolved incident needs its resolution fields. - Seeded rows get stable sys_ids, so seeding again on saved state adds nothing.
-
Without config the instance has
admin/adminand the base rolesadmin,itil,itil_admin,user_admin,snc_read_only, andsnc_internal.
Inspector
GET /_inspector shows incidents, changes, problems, users with their effective roles, groups, tables with row counts, attachments, and OAuth clients.
Limits
Outbound webhooks and business rule scripts (ServiceNow has no standard signed webhook), the Import Set, CMDB, Service Catalog, and Scripted REST APIs, approvals (sysapproval_approver), SLAs, workflows and flows, UI policies, domain separation, XML responses, and sysparm_view. ACLs are the model above rather than configurable rules.
Conformance
See CONFORMANCE.md for every provider.