API & webhooks
AJAX REST API Example with XMLHttpRequest and Explicit Errors
Use asynchronous XMLHttpRequest for a JSON REST endpoint, check HTTP status, and handle parsing, timeout, network failure, and cancellation separately.
AJAX describes asynchronous browser communication
An AJAX request lets a browser exchange data without navigating the entire page. It does not require XML, and it does not require jQuery. XMLHttpRequest remains useful in applications that already use its event model or need its transfer-progress events. Fetch is another option with a promise-oriented interface.
The XMLHttpRequest guide covers request creation and response handling. This example uses an asynchronous GET and expects a JSON document on success. It does not implement form submission, file upload or a general-purpose HTTP client.
Return a promise and a cancellation handle
function getJsonXHR(url) {
const xhr = new XMLHttpRequest();
const promise = new Promise((resolve, reject) => {
xhr.open("GET", url, true);
xhr.timeout = 5000;
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = () => {
if (xhr.status < 200 || xhr.status >= 300) {
reject(new Error(`HTTP ${xhr.status}`));
return;
}
try { resolve(JSON.parse(xhr.responseText)); }
catch { reject(new Error("The response is not valid JSON.")); }
};
xhr.onerror = () => reject(new Error("Network request failed."));
xhr.ontimeout = () => reject(new Error("Request timed out."));
xhr.onabort = () => reject(new Error("Request cancelled."));
xhr.send();
});
return {promise, cancel: () => xhr.abort()};
}
Call getJsonXHR to start the request, then await its promise in a try/catch block. Keep the returned cancel function if the interface offers a Cancel action or if navigation should retire the operation. Calling cancel after completion does not undo a server operation that has already happened.
The code registers handlers before sending. A load event means the transfer completed; it does not guarantee a successful HTTP status. The explicit status check prevents a readable 404 body from being mistaken for successful application data.
Make the successful-body contract explicit
The helper parses responseText as JSON. A successful body containing null is valid JSON and resolves to null, while an empty body or malformed document is rejected. If the endpoint legitimately returns 204 with no content, add that case intentionally rather than using this helper unchanged and calling the empty response a server defect.
After parsing, validate the structure the application needs. An array, object and number are all possible JSON values. Parsing alone cannot establish that a response contains a notes collection or a specific required field. Keep that application check separate from transport and JSON syntax.
Keep network failure, timeout and cancellation distinct
A network error can result from connectivity or browser access restrictions. A timeout means this request did not finish within its configured limit. Cancellation is an intentional interruption. Reporting all three as an HTTP 500 invents a server response the client may never have received.
The five-second timeout is an example limit, not a universal recommendation for every API. Choose a bound appropriate to the operation and show a meaningful state while it is pending. Do not switch to synchronous XHR to avoid writing asynchronous handling; blocking the main thread harms the interface.
Respect the same browser integration constraints
Using XMLHttpRequest instead of fetch does not bypass CORS. A cross-origin service still needs to permit the request. Configure credentialed requests only according to the service's authentication and cross-site request policy, and keep secrets intended for a server out of the browser bundle.
If several requests can update the same part of the page, attach an ownership or sequence check at the rendering layer. Cancelling an earlier transfer helps, but a late callback should still be prevented from overwriting a newer selection. The helper intentionally returns data and leaves that interface policy to its caller.
Exercise every completion path
Use controlled fixtures for valid JSON, valid null, a 404, malformed JSON, a delayed timeout and cancellation. Assert the exact branch taken and confirm that the promise settles rather than leaving the interface indefinitely loading. Add the endpoint's application-shape tests after those transport checks.
The REST API Testing Tool can inspect an authorized endpoint's raw status and response. It does not test your XHR event handlers or Cancel button. Verify those behaviors in the page that uses the helper, including a successful request immediately after a cancelled one.
If you later add a progress indicator, distinguish a known total from an unknown one. A response without a computable length cannot supply a reliable percentage from transferred bytes alone. Show an indeterminate state instead, and finish it only when the relevant completion or failure event occurs.


