Error Codes
When a request fails, Corvo returns a JSON error envelope with a stable machine-readable code and a human-readable message.
Response400Error envelope
{
"error": {
"message": "Either name or company is required",
"code": "VALIDATION_ERROR"
}
}
const response = await fetch("https://corvo.to/api/v1/shipments", options);
if (!response.ok) {
const { error } = await response.json();
switch (error.code) {
case "RATE_LIMITED":
console.error("retry after", response.headers.get("Retry-After"));
break;
case "RATE_EXPIRED":
console.error("recreate the draft before buying again");
break;
default:
console.error(error.code, error.message);
}
}
Reference
Authentication
| Code | HTTP | Description |
|---|
| UNAUTHORIZED | 401 | Missing authentication. |
| INVALID_API_KEY | 401 | Malformed, revoked, or unknown API key. |
| EMAIL_NOT_VERIFIED | 403 | The key owner must verify their email before creating shipments. |
Documents
| Code | HTTP | Description |
|---|
| UPLOAD_QUOTA_EXCEEDED | 429 | Too many unattached pending or confirmed uploads for the organization. |
| UPLOAD_NOT_FOUND | 404 | Unknown tracked upload ID or missing pending object. |
| UPLOAD_ALREADY_CONFIRMED | 409 | The tracked upload was already confirmed. |
| UPLOAD_EXPIRED | 410 | The tracked upload expired before confirmation. |
| PDF_TOO_LARGE | 400 | The uploaded PDF exceeds 50 MB. |
| INVALID_PDF | 400 | The file is not a valid PDF. |
| ENCRYPTED_PDF | 400 | Password-protected PDFs are not supported. |
| EMPTY_PDF | 400 | The PDF contains zero pages. |
Shipments
| Code | HTTP | Description |
|---|
| VALIDATION_ERROR | 400 | Request body, query params, or path params failed validation. |
| DOCUMENT_NOT_FOUND | 404 | The referenced document key was not found for this organization. |
| SHIPMENT_NOT_FOUND | 404 | No shipment exists with that ID for the authenticated organization. |
| RATE_NOT_FOUND | 404 | The selected quote does not belong to the shipment. |
| RATE_EXPIRED | 410 | The draft quote expired. Recreate the draft and select a fresh quote. |
| INVALID_STATUS_TRANSITION | 409 | The requested transition is not allowed from the shipment's current state. |
| NOT_CERTIFIED_MAIL | 400 | Mailing record summaries are only available for certified-mail shipments. |
| NO_TRACKING_NUMBER | 400 | Mailing record summary and evidence-bundle downloads require a purchased shipment with a tracking number. |
| EVIDENCE_EXPIRED | 410 | The shipment's evidence retention window has elapsed. Evidence downloads are no longer available. |
Billing and upstream services
| Code | HTTP | Description |
|---|
| CUSTOMER_NOT_FOUND | 400 | The organization has no Stripe customer configured. |
| NO_PAYMENT_METHOD | 400 | The organization has no default payment method on file. |
| PAYMENT_FAILED | 402 | Stripe could not capture the charge. |
| ADDRESS_VERIFICATION_FAILED | 502 | Carrier address verification failed. |
| SHIPMENT_CREATION_FAILED | 502 | EasyPost could not create the shipment for quoting. |
| RATE_PURCHASE_FAILED | 502 | EasyPost could not buy the selected rate. |
| PRICING_NOT_CONFIGURED | 500 | Corvo pricing configuration is missing or invalid. |
System
| Code | HTTP | Description |
|---|
| RATE_LIMITED | 429 | Application-level rate limit exceeded. |
| INTERNAL_ERROR | 500 | Unexpected untyped server error. |