OBLYTECH Logo
OBLYTECH Logo
ServiceNow REST and SOAP Integrations Best Practices

ServiceNow REST and SOAP Integrations Best Practices

This guide covers six areas of ServiceNow API integration: choosing an authentication method, handling rate limits with backoff, logging and error handling, managing API versions, testing happy and error paths, and documenting each integration for future maintenance.

Choose Authentication Methods Based on Security Requirements and System Capabilities

ServiceNow supports multiple authentication methods for APIs: OAuth 2.0 for user-delegated access, API tokens for service-to-service authentication, and basic authentication for legacy systems. OAuth 2.0 is most secure for public or multi-tenant integrations because it does not require sharing credentials; users authenticate with their own account, and the external system receives a limited-scope token. API tokens are appropriate for service-to-service integrations where one system needs to call ServiceNow; create a dedicated service account and issue tokens with permissions limited to specific tables and fields. Avoid basic authentication (username and password in the API call) for production integrations because credentials are exposed in logs and can be compromised. For integrations with legacy systems that support only basic authentication, run the integration through a secure intermediary that can handle OAuth on the public side and translate to basic auth for the legacy system. Document what authentication method you chose and why for each integration.

Implement Rate Limiting and Backoff to Protect Service Reliability

An API call that returns data instantly when one client calls might slow down or time out when many clients call simultaneously. ServiceNow has API rate limits to prevent one integration from overwhelming the system. When building an integration, implement backoff logic: if an API call fails with a rate limit error (HTTP 429), wait a few seconds before retrying, not immediately. Implement exponential backoff for resilience: wait 1 second, then 2 seconds, then 4 seconds if failures continue. Calculate the API call volume your integration will generate and test it in a non-production instance to verify you will not exceed rate limits. For high-volume integrations that might approach rate limits, use pagination to fetch data in smaller chunks instead of requesting all data at once. Monitor API usage from your integration and alert if usage patterns change unexpectedly.

Build Comprehensive Logging and Error Handling Into All API Calls

An API integration that works perfectly in testing sometimes encounters unexpected responses in production: null values, missing fields, changed data formats, or external system errors. Every API call should have error handling: check for HTTP errors (4xx and 5xx responses), validate that required fields are present in the response, and handle edge cases like empty result sets. Log every API call with timestamp, endpoint, request parameters, response status, and response data (or at least response summary) so you can diagnose problems after they occur. Include human-readable error messages in logs, not just error codes, so you can quickly understand what went wrong. Avoid logging sensitive data like passwords or API tokens; redact those in log output. Use a centralized logging system that retains logs for a period set by the platform owner so you can investigate incidents that occurred in the past.

Manage API Versions and Plan for Backward Compatibility

APIs change over time: new fields are added, old fields are deprecated, response formats change. ServiceNow provides API versioning so integrations do not break automatically when new versions are released. Always specify an API version in your integration (for example, /api/now/v2/table/incident) rather than using the default latest version. When you upgrade your ServiceNow instance, check the release notes to see if API changes affect your integrations. Plan to update integrations gradually: identify which integrations are affected, test them in your test instance first, and update to the latest API version in a controlled manner. Maintain backward compatibility in integrations you build so that clients can continue using older API versions while they make their own updates.

Implement Testing Scenarios for Happy Path and Error Cases

Test an integration with normal data in your test instance, but also test what happens when the integration encounters errors: what if the external system is down, what if a required field is missing, what if the response is larger than expected? Use chaos testing to deliberately introduce failures and verify your integration handles them gracefully. Test performance by calling your API with high concurrency to simulate multiple clients calling simultaneously. Test data quality by passing unusual values (very long strings, special characters, SQL-like patterns) to verify your integration does not break or introduce security issues. Build these test scenarios into your deployment process so they run automatically before the integration is deployed to production.

Document APIs and Integration Points for Future Maintenance

An undocumented integration is a maintenance nightmare for future developers. Document the purpose of the integration, what data is transferred, how often it runs, and what happens if it fails. Document authentication (which credentials are needed, where they are stored), rate limits you are subject to, and what to do if you encounter unexpected errors. List the tables and fields the integration accesses so you know the scope of access. Document the response format and what values you expect so future developers can spot unexpected changes quickly. Store this documentation in a version control system or wiki alongside the integration code so it stays synchronized.

Design the payload contract before the first call

Many integration disputes are about the shape of the data rather than the transport. What the sender puts in a request, what the receiver returns, and which values count as empty are decided by a contract, and the contract is easier to agree on before code exists. Write it down as a short table per endpoint: field name, type, whether it is required, what a missing value means, and whether it is a reference to another record or a plain value. A contract that exists on paper can be checked in testing, and one that lives only in a developer’s head changes without anyone noticing.

Ask for exactly the fields the consumer needs

When a consumer pulls records from the Table API, the field list controls both the payload size and the coupling between the two systems. A consumer that asks for every column is exposed to any new column that carries sensitive or irrelevant data, and it breaks when a column is renamed. Name the fields explicitly, and keep the list short enough that a reviewer can explain each entry. Display values make sense for a person reading the output, but a system that stores the result should usually keep the raw identifier for references and convert labels only at the edge.

Decide how bulk requests report partial failure

A bulk endpoint that accepts fifty records and fails on the twelfth has three possible behaviors: reject the whole batch, accept the good rows and report the bad ones, or accept everything and fail later. Each suits a different business rule. Rejecting the whole batch is simplest but forces a resend of valid data. Accepting good rows is efficient but requires the sender to read a per-row result and act on it. Choose the behavior in the contract and make the response structure match it, so the sender never has to guess which rows were stored.

Need Parameter or pattern to prefer Trade-off to record
Read only what a process uses An explicit field list New fields need a deliberate change to the consumer
Show labels to people, keep identifiers for systems Display values for reports, raw values for storage Two shapes of the same data must be kept apart
Walk through a large table Limit and offset, or a stable sort key with a last-seen value Offset paging can skip or repeat rows when data changes during a run
Send many records at once A batch with per-row results The sender must parse and retry individual rows
Find out what changed since the last run A last-updated filter with a stored watermark Clock differences need care, and the watermark must move only after success

Standardize the error envelope

An error response should tell the caller three things: what category of failure occurred, whether a retry can help, and which record or field caused it. Teams that return a plain status code and a free-text message force every consumer to write its own parser. A consistent envelope, with the same field names on every endpoint, lets monitoring group failures by type and lets the sender decide automatically whether to retry. Keep the message readable by a person, and keep sensitive values out of it.

Handle time with one rule

Timestamps often cause silent defects. Pick one rule and apply it everywhere: store and exchange times in a single reference zone, state that zone in the contract, and convert only when a person reads the value. Mixing local times from one source with UTC from another produces records that look correct on screen and sort wrongly in reports. Test with a record created near midnight in a zone far from the instance’s own.

An ordered review before a contract is approved

  1. Confirm every endpoint has a table of fields, types and required flags.
  2. Confirm each field list is explicit and each excluded sensitive field is named as excluded.
  3. Confirm the bulk behavior on partial failure is written into the contract and reflected in the response shape.
  4. Confirm the error envelope is the same across endpoints and marks retryable failures.
  5. Confirm one time-zone rule applies to every timestamp field, with a test record near a day boundary.

Questions about contract design

Should the consumer or the provider own the field list?

The consumer should state what it needs and the provider should publish what it will expose. Where the two differ, the provider decides what is safe to share, and the consumer adapts its request. Agreeing this early avoids a later argument about a field that was never meant to leave the instance.

Why do offset-based reads sometimes return duplicate rows?

If rows are inserted or updated between pages, the offset points at a different position than the one the reader expected. A stable sort key and a last-seen value are more reliable for large, changing tables.

Is it acceptable to return display values to another system?

It works until a label changes or is translated. Store identifiers wherever a system will later match or update records, and reserve labels for people.

Walk the contract through with the consumer

Contracts are easier to change before a consumer depends on them. Who may call these endpoints is a separate question, and the security and access design guide handles that. The article on API contract versioning covers how versions change once a contract is published, and the piece on scripted REST API design contracts goes further into endpoints that ServiceNow itself exposes. The explainer on outbound REST messages describes how ServiceNow sends data to an external system.

Frequently asked questions

How should we handle sensitive data like passwords or personal information in API calls?

Use HTTPS for all API calls to encrypt data in transit. Store credentials in ServiceNow's Credentials entity, not in integration code. Do not log sensitive data; redact it from logs. If the external system requires credentials, use a secure credential store or vault, not plain text files.

What should we do if an external API changes unexpectedly and breaks our integration?

Build error handling so that unexpected responses do not cause cascading failures. Alert your team when API behavior changes. If possible, reach out to the external system's support team to understand the change. Plan gradual migration to new API formats rather than being forced to update urgently.

How do we retry failed API calls without creating duplicate records?

Use idempotency keys or unique identifiers to prevent duplicates: if you retry a failed create request with the same key, the system recognizes it as a retry and does not create a duplicate. Check for existing records before creating new ones. Use transactional patterns where possible to roll back changes if part of an operation fails.

Talk to Oblytech

Planning, running or fixing a ServiceNow programme? Tell us where you are and we will suggest a sensible next step.

Contact us