Documentation Index Fetch the complete documentation index at: https://mintlify.com/paynow-gg/typescript-sdk/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The PayNow SDK provides built-in error handling utilities to help you distinguish between PayNow API errors and other types of failures. All API errors follow a consistent structure defined by the PayNow API specification.
PayNowError Type
The SDK exports a specialized PayNowError type that represents errors returned by the PayNow API:
// From src/errors.ts:4-6
export type PayNowError = AxiosError < components [ "schemas" ][ "PayNowError" ]> & {
response : AxiosResponse < components [ "schemas" ][ "PayNowError" ]>;
};
This type extends Axios’s AxiosError with PayNow-specific error schema information and guarantees that a response property exists.
Error Structure
PayNow API errors have the following structure:
{
status : number ; // HTTP status code
code : string ; // PayNow error code
message : string ; // Human-readable error message
}
Type Guard: isPayNowError
The SDK provides a type guard function to safely check if an error is a PayNow API error:
import { isPayNowError } from '@paynow-gg/typescript-sdk' ;
Implementation
// From src/errors.ts:8-18
export function isPayNowError ( error : unknown ) : error is PayNowError {
return (
error instanceof AxiosError &&
!! error . response &&
typeof error . response . data === "object" &&
error . response . data !== null &&
"status" in error . response . data &&
"code" in error . response . data &&
"message" in error . response . data
);
}
This function validates that:
The error is an Axios error
A response exists (not a network/timeout error)
The response data is an object
The object contains status, code, and message fields
Basic Error Handling
Here’s how to handle errors in your application:
import { createStorefrontClient , isPayNowError } from '@paynow-gg/typescript-sdk' ;
const storefront = createStorefrontClient ( 'your-store-id' );
try {
const response = await storefront . products . getProduct ({
path: { productId: 'invalid-id' },
});
console . log ( response . data );
} catch ( error ) {
if ( isPayNowError ( error )) {
// This is a PayNow API error
console . error ( 'PayNow API Error:' , {
status: error . response . data . status ,
code: error . response . data . code ,
message: error . response . data . message ,
});
} else {
// This is some other error (network, timeout, etc.)
console . error ( 'Unexpected error:' , error );
}
}
Error Handling Patterns
Simple Try-Catch
Error Code Handling
Async/Await with Multiple Requests
Custom Error Handler
try {
const response = await storefront . orders . createOrder ({
data: { productId: '123' , quantity: 1 },
});
return response . data ;
} catch ( error ) {
if ( isPayNowError ( error )) {
throw new Error ( `Failed to create order: ${ error . response . data . message } ` );
}
throw error ;
}
Non-PayNow Errors
Not all errors are PayNow API errors. You may encounter:
Network Errors
try {
const response = await storefront . store . getStorefrontStore ();
} catch ( error ) {
if ( error instanceof AxiosError && ! error . response ) {
// Network error - no response from server
console . error ( 'Network error:' , error . message );
}
}
Timeout Errors
const storefront = createStorefrontClient ( 'store-id' , undefined , {
timeout: 5000 , // 5 second timeout
});
try {
const response = await storefront . products . listProducts ();
} catch ( error ) {
if ( error instanceof AxiosError && error . code === 'ECONNABORTED' ) {
console . error ( 'Request timed out' );
}
}
Request Cancellation
import axios from 'axios' ;
const controller = new AbortController ();
const storefront = createStorefrontClient ( 'store-id' );
try {
const response = await storefront . products . listProducts ({
signal: controller . signal ,
});
} catch ( error ) {
if ( axios . isCancel ( error )) {
console . log ( 'Request cancelled' );
}
}
// Cancel the request
controller . abort ();
Error Response Structure
When isPayNowError returns true, you can safely access:
if ( isPayNowError ( error )) {
// All of these are guaranteed to exist and be typed correctly
const status = error . response . data . status ; // number
const code = error . response . data . code ; // string
const message = error . response . data . message ; // string
// Standard Axios error properties
const httpStatus = error . response . status ; // number
const headers = error . response . headers ; // object
const config = error . config ; // AxiosRequestConfig
}
Best Practices
Always use the type guard
Always use isPayNowError() before accessing error properties. This provides type safety and prevents runtime errors: // ✅ Good
if ( isPayNowError ( error )) {
console . log ( error . response . data . code );
}
// ❌ Bad - TypeScript doesn't know the error structure
console . log ( error . response . data . code );
Don’t assume all errors are PayNow errors. Network issues, timeouts, and other failures can occur: try {
await client . products . listProducts ();
} catch ( error ) {
if ( isPayNowError ( error )) {
// Handle PayNow API error
} else if ( error instanceof AxiosError ) {
// Handle other Axios errors (network, timeout, etc.)
} else {
// Handle unexpected errors
}
}
Include relevant error information when logging: if ( isPayNowError ( error )) {
console . error ( 'PayNow API Error:' , {
status: error . response . data . status ,
code: error . response . data . code ,
message: error . response . data . message ,
url: error . config ?. url ,
method: error . config ?. method ,
});
}
Provide user-friendly messages
Don’t expose raw API error messages to end users. Map error codes to user-friendly messages: const userFriendlyMessage = ( error : PayNowError ) : string => {
const errorMessages : Record < string , string > = {
'PRODUCT_NOT_FOUND' : 'This product is no longer available.' ,
'INSUFFICIENT_STOCK' : 'This item is out of stock.' ,
'INVALID_PAYMENT' : 'Payment failed. Please check your payment details.' ,
};
return errorMessages [ error . response . data . code ]
|| 'Something went wrong. Please try again.' ;
};
Next Steps
Authentication Understand how authentication works in the SDK
Client Architecture Learn about the client structure and type safety