Skip to content
Last updated

Errors & Rate Limits

When an API request fails, ShipSaving returns a structured error response with a machine-readable code and a human-friendly msg. This page documents the error response format, HTTP status codes and rate limits.


Error Response Format

All API responses — including errors — share the same JSON structure:

Success response:

{
  "code": "ok",
  "msg": "ok",
  "data": { ... }
}

Error response:

{
  "code": "shipment.address.city_can_not_be_null",
  "msg": "City is required.",
  "data": null
}
FieldTypeDescription
codestring"ok" on success; a dot-separated error code on failure (e.g. shipment.buy.pay_shipment_failed).
msgstringA human-readable message describing the result.
dataobject / nullThe response payload on success; null on failure.

HTTP Status Codes

CodeMeaningWhen It Happens
200OKRequest succeeded. Check the code field — "ok" means success.
400Bad RequestThe request contains invalid parameters, missing required fields, or a business logic violation. The code field contains a specific error code.
401UnauthorizedAccess token is missing, expired, or invalid. Obtain a new token via /oauth2/token.
429Too Many RequestsYou have exceeded the rate limit.
500Internal Server ErrorAn unexpected error occurred on our side. If this persists, contact support.

Error Code Convention

Error codes follow a dot-separated naming pattern that indicates the domain and specific issue:

{domain}.{subdomain}.{detail}

For example:

  • shipment.address.city_can_not_be_null — Shipment domain → Address subdomain → City is missing
  • common.transaction.wallet_balance_not_enough — Common domain → Transaction subdomain → Insufficient balance

This pattern helps you programmatically categorize errors in your integration.

Exception

The /oauth2/token endpoint follows the OAuth 2.0 error format and does not use the dot-separated convention above. See Authentication for details.


Rate Limits

Rate limits are applied at three levels:

LevelScopeDescription
App KeyPer API keyEach app_key has its own allowance. One busy integration won't affect your other keys.
CompanyPer accountAll API keys under the same company share a combined limit, even if you use multiple keys.
GlobalPlatform-wideA system-wide cap across all users. If the platform is under heavy load, requests may be rejected even if your key has room.

A request must pass all applicable levels. If any one of them is exceeded, the request is rejected.

Limits may vary

Limits differ by endpoint and account tier, and may change over time. If you need higher throughput, contact your account manager.

When you exceed the limit, the API returns HTTP 429 with error code common.check.rate_limit:

{
  "code": "common.check.rate_limit",
  "msg": "request too frequent",
  "data": null
}

Handling Recommendations

  1. Check the code field, not just HTTP status.
    A 200 response with "code": "error" is still an error. Always check code == "ok" before processing data.

  2. Handle authentication errors gracefully.
    There are two types of 401 errors:

  • Invalid credentials: If /oauth2/token returns 401 with {"error": "invalid_client"}, your app_key or app_secret is incorrect. Double-check your credentials — do not retry.

  • Expired access token: If any other API endpoint returns 401 with an empty body, your access token has expired. Request a new token from /oauth2/token and retry the original request.

  1. Implement retry with backoff for transient errors.
    For errors like common.redis_lock.system_busy, shipment.pay.get_pay_lock_failed, or common.check.rate_limit, retry with exponential backoff:

    Wait 1s → retry → wait 2s → retry → wait 4s → retry → give up
  2. Do not retry validation errors.
    Errors in the shipment.address.*, shipment.package.*, and shipment.custom.* categories indicate invalid input. Fix the request parameters before retrying.

  3. Use platform_uk_id to prevent duplicate shipments.
    If you receive a timeout or ambiguous response during label purchase, query the shipment status before retrying. The shipment.current_platform_uk_id_already_create_shipment error protects against duplicate charges.