This guide covers how to handle errors from the Triqai API, including common error codes, troubleshooting tips, and best practices.
All error responses follow a consistent structure:
{
"success" : false ,
"error" : {
"code" : "error_code" ,
"message" : "Human-readable description" ,
"details" : { /* optional additional info */ }
},
"meta" : {
"generatedAt" : "2026-01-19T10:30:00Z" ,
"requestId" : "3c90c3cc-0d44-4b50-8888-8dd25736052a123" ,
"version" : "1.1.9"
}
}
Error Codes
Authentication Errors (401)
Code Message Solution authentication_errorInvalid or missing API key Check your X-API-Key header authentication_errorInvalid API key format Ensure key starts with triq_
import { AuthenticationError } from "triqai" ;
try {
await triqai . transactions . enrich ({ title: "TEST" , country: "US" , type: "expense" });
} catch ( err ) {
if ( err instanceof AuthenticationError ) {
console . error ( "API key invalid. Please check your configuration." );
}
}
Payment Errors (402)
Code Message Solution insufficient_creditsInsufficient credits Enable overages or upgrade plan
import { InsufficientCreditsError } from "triqai" ;
try {
await triqai . transactions . enrich ({ title: "TEST" , country: "US" , type: "expense" });
} catch ( err ) {
if ( err instanceof InsufficientCreditsError ) {
console . log ( "Top up credits at https://triqai.com/dashboard" );
}
}
Not Found Errors (404)
Code Message Solution not_foundResource not found Verify the ID exists
import { NotFoundError } from "triqai" ;
try {
await triqai . transactions . get ( "nonexistent-id" );
} catch ( err ) {
if ( err instanceof NotFoundError ) {
console . error ( "Resource not found" );
}
}
Validation Errors (422)
Code Message Details validation_errorValidation failed fieldErrors object with per-field errors
{
"error" : {
"code" : "validation_error" ,
"message" : "Validation failed" ,
"details" : {
"fieldErrors" : {
"title" : [ "Title is required" ],
"country" : [ "Invalid country code. Use ISO 3166-1 alpha-2 format." ],
"type" : [ "Type must be 'expense' or 'income'" ]
}
}
}
}
import { ValidationError } from "triqai" ;
try {
await triqai . transactions . enrich ({ title: "" , country: "INVALID" , type: "expense" });
} catch ( err ) {
if ( err instanceof ValidationError ) {
console . log ( "Field errors:" , err . fieldErrors );
// { title: ["Title is required"], country: ["Invalid country code"] }
}
}
Rate Limit Errors (429)
Code Message Headers rate_limitedRate limit exceeded Retry-After, X-RateLimit-*
import { RateLimitError } from "triqai" ;
try {
await triqai . transactions . enrich ({ title: "TEST" , country: "US" , type: "expense" });
} catch ( err ) {
if ( err instanceof RateLimitError ) {
console . log ( `Rate limited. Retry after ${ err . rateLimitInfo . retryAfter } s` );
}
}
Rate-limited requests are automatically retried with exponential backoff, so you typically don’t need to handle 429 errors manually.
Server Errors (500)
Code Message Solution internal_errorAn unexpected error occurred Retry with exponential backoff
import { InternalServerError } from "triqai" ;
// 500 errors are retried automatically (up to 3 times by default).
// You can customize this behavior:
const triqai = new Triqai ( process . env . TRIQAI_API_KEY ! , {
maxRetries: 5 ,
retryDelay: 1000 ,
});
Automatic Retries
Retries are handled automatically with exponential backoff. You can customize the retry behavior:
import Triqai from "triqai" ;
const triqai = new Triqai ( process . env . TRIQAI_API_KEY ! , {
maxRetries: 3 , // max retry attempts (default: 3)
retryDelay: 500 , // base delay in ms (default: 500)
maxRetryDelay: 30_000 , // max delay cap (default: 30000)
});
Retry behavior:
GET and DELETE requests are always retried on transient errors
POST requests are only retried when an idempotencyKey is provided
The Retry-After header from 429 responses is respected automatically
Retried status codes: 429, 500, 503, 504, and network errors
To disable retries entirely:
const triqai = new Triqai ( process . env . TRIQAI_API_KEY ! , { maxRetries: 0 });
Complete Error Handling Pattern
Here’s a complete error handling example using typed error classes:
import Triqai , {
TriqaiError ,
AuthenticationError ,
ValidationError ,
RateLimitError ,
InsufficientCreditsError ,
NotFoundError ,
} from "triqai" ;
const triqai = new Triqai ( process . env . TRIQAI_API_KEY ! );
try {
const result = await triqai . transactions . enrich ({
title: "STARBUCKS NYC" ,
country: "US" ,
type: "expense" ,
});
} catch ( err ) {
if ( err instanceof AuthenticationError ) {
console . error ( "Invalid API key — check your configuration" );
} else if ( err instanceof ValidationError ) {
console . log ( "Validation errors:" , err . fieldErrors );
} else if ( err instanceof RateLimitError ) {
console . log ( `Rate limited — retry after ${ err . rateLimitInfo . retryAfter } s` );
} else if ( err instanceof InsufficientCreditsError ) {
console . log ( "No credits remaining — top up at triqai.com/dashboard" );
} else if ( err instanceof NotFoundError ) {
console . log ( "Resource not found" );
} else if ( err instanceof TriqaiError ) {
console . log ( `API error ${ err . statusCode } : ${ err . message } [ ${ err . code } ]` );
console . log ( "Request ID:" , err . requestId );
}
}
See the error handling reference for the full list of error classes.
Logging and Monitoring
Request Logging
Use built-in debug hooks for observability:
const triqai = new Triqai ( process . env . TRIQAI_API_KEY ! , {
onRequest : ( info ) => {
console . log ( `→ ${ info . method } ${ info . url } ` );
},
onResponse : ( info ) => {
console . log ( `← ${ info . status } in ${ info . durationMs } ms` );
},
});
Or wrap calls for custom logging:
async function enrichWithLogging ( transaction : { title : string ; country : string ; type : string }) {
const startTime = Date . now ();
try {
const result = await triqai . transactions . enrich ( transaction );
console . log ({ event: "enrichment_success" , duration: Date . now () - startTime });
return result ;
} catch ( err ) {
if ( err instanceof TriqaiError ) {
console . error ({ event: "enrichment_error" , code: err . code , requestId: err . requestId });
}
throw err ;
}
}
Error Tracking
import { TriqaiError } from "triqai" ;
function trackError ( error : TriqaiError , context : Record < string , unknown > = {}) {
errorTracker . captureException ( error , {
tags: {
service: "triqai" ,
errorCode: error . code ,
},
extra: {
requestId: error . requestId ,
statusCode: error . statusCode ,
... context ,
},
});
}
Best Practices
Always include requestId in logs
The meta.requestId helps with debugging and support requests.
Implement circuit breakers for high-volume
If errors persist, temporarily stop requests to prevent cascading failures.
Handle partial results separately
Partial results (partial: true) are successes with some failures handle them differently from full failures.
Validate input before sending
Catch validation errors client-side when possible to reduce failed API calls.
Use structured error classes
Create error classes that make it easy to check error types and extract details.
Next Steps
API Reference Complete API documentation with error codes
Rate Limits Understand and manage rate limits