Skip to Content

REST API Response Helper

Standardized functions for formatting and handling REST API responses with consistent error handling.

#rest-api #api #response-formatting #error-handling #scripted-rest #web-services

Script Code

JavaScript
1var RestResponseHelper = Class.create();
2RestResponseHelper.prototype = {
3
4  /**
5   * Create success response
6   * @param {object} data - Response data
7   * @param {string} message - Optional success message
8   * @param {number} statusCode - HTTP status code (default: 200)
9   * @returns {object} Formatted response
10   */
11  success: function(data, message, statusCode) {
12    return {
13      status: 'success',
14      code: statusCode || 200,
15      message: message || 'Request completed successfully',
16      data: data,
17      timestamp: new GlideDateTime().getValue()
18    };
19  },
20
21  /**
22   * Create error response
23   * @param {string} message - Error message
24   * @param {number} statusCode - HTTP status code (default: 400)
25   * @param {object} details - Additional error details
26   * @returns {object} Formatted error response
27   */
28  error: function(message, statusCode, details) {
29    return {
30      status: 'error',
31      code: statusCode || 400,
32      message: message || 'An error occurred',
33      error: details || {},
34      timestamp: new GlideDateTime().getValue()
35    };
36  },
37
38  /**
39   * Create validation error response
40   * @param {array} errors - Array of validation errors
41   * @returns {object} Formatted validation error
42   */
43  validationError: function(errors) {
44    return {
45      status: 'error',
46      code: 422,
47      message: 'Validation failed',
48      errors: errors,
49      timestamp: new GlideDateTime().getValue()
50    };
51  },
52
53  /**
54   * Create not found response
55   * @param {string} resource - Resource type (e.g., 'User', 'Incident')
56   * @param {string} identifier - Resource identifier
57   * @returns {object} Formatted not found response
58   */
59  notFound: function(resource, identifier) {
60    return {
61      status: 'error',
62      code: 404,
63      message: resource + ' not found' + (identifier ? ': ' + identifier : ''),
64      timestamp: new GlideDateTime().getValue()
65    };
66  },
67
68  /**
69   * Create unauthorized response
70   * @param {string} message - Optional message
71   * @returns {object} Formatted unauthorized response
72   */
73  unauthorized: function(message) {
74    return {
75      status: 'error',
76      code: 401,
77      message: message || 'Unauthorized - Authentication required',
78      timestamp: new GlideDateTime().getValue()
79    };
80  },
81
82  /**
83   * Create forbidden response
84   * @param {string} message - Optional message
85   * @returns {object} Formatted forbidden response
86   */
87  forbidden: function(message) {
88    return {
89      status: 'error',
90      code: 403,
91      message: message || 'Forbidden - Insufficient permissions',
92      timestamp: new GlideDateTime().getValue()
93    };
94  },
95
96  /**
97   * Create paginated response
98   * @param {array} data - Array of results
99   * @param {number} page - Current page number
100   * @param {number} pageSize - Results per page
101   * @param {number} total - Total number of results
102   * @returns {object} Formatted paginated response
103   */
104  paginated: function(data, page, pageSize, total) {
105    var totalPages = Math.ceil(total / pageSize);
106
107    return {
108      status: 'success',
109      code: 200,
110      data: data,
111      pagination: {
112        page: page,
113        pageSize: pageSize,
114        totalResults: total,
115        totalPages: totalPages,
116        hasNext: page < totalPages,
117        hasPrevious: page > 1
118      },
119      timestamp: new GlideDateTime().getValue()
120    };
121  },
122
123  /**
124   * Format GlideRecord as REST response
125   * @param {GlideRecord} gr - GlideRecord object
126   * @param {array} fields - Fields to include (optional, defaults to all)
127   * @returns {object} Formatted record object
128   */
129  formatRecord: function(gr, fields) {
130    if (!gr || !gr.isValidRecord()) {
131      return null;
132    }
133
134    var record = {
135      sys_id: gr.sys_id.toString(),
136      sys_created_on: gr.sys_created_on.toString(),
137      sys_updated_on: gr.sys_updated_on.toString()
138    };
139
140    if (fields && fields.length > 0) {
141      // Include only specified fields
142      fields.forEach(function(field) {
143        if (gr.isValidField(field)) {
144          record[field] = gr[field].toString();
145          record[field + '_display'] = gr[field].getDisplayValue();
146        }
147      });
148    } else {
149      // Include all fields
150      var fieldNames = gr.getFields();
151      for (var i = 0; i < fieldNames.size(); i++) {
152        var fieldName = fieldNames.get(i).getName();
153        record[fieldName] = gr[fieldName].toString();
154
155        // Add display value for reference fields
156        if (gr[fieldName].getReferenceTable()) {
157          record[fieldName + '_display'] = gr[fieldName].getDisplayValue();
158        }
159      }
160    }
161
162    return record;
163  },
164
165  /**
166   * Format multiple GlideRecords as array
167   * @param {GlideRecord} gr - GlideRecord with query results
168   * @param {array} fields - Fields to include (optional)
169   * @param {number} maxResults - Maximum results to return
170   * @returns {array} Array of formatted records
171   */
172  formatRecords: function(gr, fields, maxResults) {
173    var records = [];
174    maxResults = maxResults || 1000;
175    var count = 0;
176
177    while (gr.next() && count < maxResults) {
178      records.push(this.formatRecord(gr, fields));
179      count++;
180    }
181
182    return records;
183  },
184
185  /**
186   * Validate required fields in request
187   * @param {object} request - Request object
188   * @param {array} requiredFields - Array of required field names
189   * @returns {object|null} Validation error response or null if valid
190   */
191  validateRequired: function(request, requiredFields) {
192    var errors = [];
193
194    requiredFields.forEach(function(field) {
195      if (!request[field] || request[field] === '') {
196        errors.push({
197          field: field,
198          message: 'Field "' + field + '" is required'
199        });
200      }
201    });
202
203    if (errors.length > 0) {
204      return this.validationError(errors);
205    }
206
207    return null;
208  },
209
210  /**
211   * Handle exception and return error response
212   * @param {Error} exception - Exception object
213   * @param {string} context - Context where error occurred
214   * @returns {object} Formatted error response
215   */
216  handleException: function(exception, context) {
217    var errorMsg = exception.message || exception.toString();
218
219    gs.error(context + ': ' + errorMsg);
220
221    return {
222      status: 'error',
223      code: 500,
224      message: 'Internal server error',
225      error: {
226        context: context,
227        details: gs.getProperty('glide.rest.verbose_errors') === 'true' ? errorMsg : undefined
228      },
229      timestamp: new GlideDateTime().getValue()
230    };
231  },
232
233  type: 'RestResponseHelper'
234};

How to Use

1. Create a new Script Include named 'RestResponseHelper' 2. Leave 'Client callable' unchecked 3. Copy the code above 4. Use in Scripted REST APIs: var helper = new RestResponseHelper(); // Success response response.setBody(helper.success({user: userData}, 'User found')); // Error response response.setBody(helper.error('Invalid user ID', 400)); // Not found response.setBody(helper.notFound('Incident', incNumber));

Explore More Scripts

Browse our complete library of ServiceNow scripts

View All Scripts