Stamps.com/Endicia REST API (SERA) (v1)

Download OpenAPI specification:Download

Stamps.com Developer Support: [email protected] URL: https://developer.stamps.com/

The Stamps.com/Endicia REST API (SERA) is the quickest and most convenient way to build a custom carrier-integrated shipping solution. If you run into any problems or have any questions along the way, contact the Stamps.com developer support team at [email protected]. Include your username, if you know it, and as much detail as possible to assist us in helping you. The fastest way for us to be able to help is by sending us a copy of the API request and response in question.

What's New

On July 9, 2023, USPS introduced a new ground-based package service: USPS Ground Advantage. This service replaces USPS First-Class Package Service, Parcel Select Ground, and Retail Ground. First-Class Mail Letters and Large Envelopes/Flats will continue to be available.

Description of Change Endpoints and Methods Impacted
usps_ground_advantage added to service_type enumeration for the new USPS Ground Advantage Service POST /v1/rates
POST /v1/labels
USPS Ground Advantage

USPS replaced the First-Class Package Service, Parcel Select Ground, and Retail Ground services with USPS Ground Advantage. Ground Advantage delivers packages within the Continental United States in 2-5 business days with free included tracking and $100 of USPS insurance for packages between 0 and 70 lbs.

USPS Ground Advantage is available as service_type usps_ground_advantage. For our customers' and partners' convenience, we will temporarily map requests for discontinued USPS package services to the new USPS Ground Advantage service. For example, after July 9, 2023, a POST /v1/labels request for service_type usps_first_class_mail and packaging_type package will return a USPS Ground Advantage label instead of a First-Class Package Service label.

Integrators are encouraged to call for USPS Ground Advantage directly with the service_type usps_ground_advantage. In the future we will communicate a date when this update will become mandatory.

About REST

SERA is a REST (REpresentational State Transfer) API, which means that it follows certain HTTP conventions for things like URLs, methods, headers, and status codes. If you’d like more information, click here.

Staging and Production Versioned Environments

The staging environment allows you to develop SERA integrations without using real funds to create test labels. There are no service or transaction fees charged for staging accounts and labels. Labels created in the staging environment cannot be used to ship and must be destroyed if printed. Access to the staging environment is available once you register for a Stamps.com developer account.

Note that shipping rates in the staging environment may vary from production and should not be relied on. Other services in staging, such as tracking and pickups, do not reflect any real-world data.

The production environment allows you to take your SERA integration live and rate-shop across multiple carriers, create real shipping labels, schedule pickups, track in-transit shipments, and more.

For the purposes of getting started, make sure to use staging credentials in the staging environment. In contrast to the production environment, the staging environment uses “play money”; it’s ideal for use while testing and getting familiar with SERA.

Endpoint Base URLs

Sign-In/Authentication

Staging: https://signin.testing.stampsendicia.com
Production: https://signin.stampsendicia.com

SERA

Staging: https://api.testing.stampsendicia.com/sera
Production: https://api.stampsendicia.com/sera

All Endpoint URLs given in this document are relative to the specific environment host you are connecting to. For example, to add funds to an account in the staging environment, POST the request to https://api.testing.stampsendicia.com/sera/v1/balance/add-funds. To do the same in the production environment, POST the request to https://api.stampsendicia.com/sera/v1/balance/add-funds.

All SERA requests must be made over HTTPS using TLS v1.2+. Calls made over plain-text HTTP or with an obsolete TLS version will fail.

Idempotency

Because the internet is not a guaranteed service, sometimes network messages (like REST API requests and responses) get lost in transit and are not received. If this happens, it’s usually impossible to know if the request was received and processed successfully, or if not, should be sent again and possibly duplicated. To guard against cases like this, be sure to include a unique Idempotency-key value in the request header when calling any SERA endpoint with the POST method.

Whenever any request does not get a response within a reasonable timeout period, simply send it again with the same Idempotency-key value. If SERA already processed a request within the past 24 hours with the same Idempotency-key, it will replay the same response without duplicating the transaction. If the key is new, SERA will process the request as normal. Idempotency-keys must be a randomly-generated version-4 UUID. Most programming languages support generating random UUIDs out-of-the-box. If an invalid Idempotency-key is included with an request, an error will be returned.

Versioning

Every SERA endpoint contains a version number in the URL. For example, to add funds to an account, call POST /v1/balance/add-funds. New versions are created to avoid impacting existing integrations when backwards-incompatible changes are introduced to SERA. Integrators are not required to upgrade versions to maintain existing functionality but may be required to upgrade to gain access to new features as they’re introduced.

Connect and Authenticate

SERA uses the industry-standard OAuth 2.0 protocol for authentication. Completing the authentication procedure for access to SERA requires a few steps.

  1. Login: Application presents the server-hosted login page to the user in a browser.
  2. Redirect with Authorization Code: Once the user logs in and authorizes the application, an authorization code is returned to the application.
  3. Initial Token Generation: Application uses authorization code to generate the initial set of access and refresh tokens.
  4. Refresh Token: Application uses the stored refresh token to generate a new access token as needed.

Login

Integrators will present the server-hosted login page to the user by displaying the /authorize page with query parameters set specific to their integration. These query parameters include the following:

  • response_type = code
  • client_id = value specific to individual application/integration
  • redirect_uri = value specific to individual application/integration
  • scope = offline_access (required to receive a refresh token)

Redirect with Authorization Code

The redirect URI must be set to a location that the application can receive the authorization code from. The specific value will depend on the type of application that is being developed.

  • Web applications can set up a callback page to receive the code query parameter.
  • Native applications have a few different options to receive the authorization code.
    • If the application is displaying the login page in an embedded web browser control, the application can extract the code query parameter value from the control's current location/URL on successful login.
    • If the application is opening the login page using a web browser application, it can receive the code either by
      • hosting a temporary local web server to receive the code (redirecting the user to http://localhost:12345/ for example) or
      • registering a custom application handler with the OS to pass the code back to the application (redirecting the user to myapp://callback/ for example, where myapp:// is configured to call the integrated application).

In any case, the redirect_uri value specific to an application must be provided in advance in order to setup a valid Client ID for use in connecting to SERA.

Initial Token Generation

Once the integrated application has a valid authorization code, it must immediately use it to call the /oauth/token endpoint for an access_token and refresh_token. While both tokens should be stored securely and confidentially, the access_token is stored for a short amount of time while the refresh_token is stored for long-term access.

The application can begin calling SERA using the access_token value in the Authorization header preceded by the word Bearer as below.

Authorization: Bearer xyz123abc987....

Refresh Token

A valid access_token is required for every SERA call and is expected to regularly expire. Once an access_token has expired or is near-expiration, the integration should used the stored refresh_token to call for a new access_token by calling the /oauth/token endpoint again.

Get Account Information

After completing the authentication process and receiving an access_token, integrators should call GET /account. The information returned is useful for an integration to configure default addresses and application capabilities.

Check Account Balance and Add Funds

Integrations should be aware of the user's account balance when initiating SERA transactions. The user's real-time account balance is available by calling GET /v1/balance. If the user's account balance is insufficient to cover a requested transaction, funds should be added to the account balance by calling POST /v1/balance/add-funds with the desired amount to add.

Viewing Shipping Rates

Before printing a label, users can call the POST /rates  endpoint to search and compare different rates for a shipment. A specific rate can then be selected for use from the returned rate options when creating a label in the next step.

The POST /rates endpoint produces a list of available rates. To narrow down the resultant list, this endpoint accepts optional information about a shipment such as the To and From addresses, as well as the package weight, type, and dimensions. Rates will vary by carrier and service_type (for example, using service_typeups_standard to receive rates for UPS Standard). Rates can also be further customized with advanced_options such as Signature Confirmation or Insurance.

If searching for a specific rate, try to include as many details as possible in the initial request. This way the returned list of available rates will be more closely tailored to the shipper’s needs. To receive an unfiltered list of available rates, try omitting any package specific information. In the following example, only the origin and destination ZIP code, package type, and package weight are provided. Try modifying the example call to reflect a specific set of shipment details and avoid errors by ensuring the ship_date is set to a date that is not in the past.

Request

{
  "from_address": {
    "postal_code": "92802"
  },
  "to_address": {
    "postal_code": "32830"
  },
  "package": {
    "packaging_type": "large_envelope",
    "weight": 24,
    "weight_unit": "ounce"
  },
  "ship_date": "{{$isoTimestamp}}"
}

Response

[
  {
    "carrier": "usps",
    "service_type": "usps_priority_mail",
    "packaging_type": "large_envelope",
    "estimated_delivery_days": "2",
    "estimated_delivery_date": "2021-09-07T21:30:14.226Z",
    "is_guaranteed_service": false,
    "trackable": "yes",
    "is_return_label": false,
    "is_customs_required": false,
    "shipment_cost": {
      "total_amount": 11.69,
      "currency": "usd",
      "cost_details": [
        {
          "fee_code": "usps_priority_mail",
          "fee_type": "service",
          "amount": 11.69
        }
      ]
    }
  },
  {
    "carrier": "usps",
    "service_type": "usps_priority_mail_express",
    "packaging_type": "large_envelope",
    "estimated_delivery_days": "1-2",
    "estimated_delivery_date": null,
    "is_guaranteed_service": true,
    "trackable": "yes",
    "is_return_label": false,
    "is_customs_required": false,
    "shipment_cost": {
      "total_amount": 45.7,
      "currency": "usd",
      "cost_details": [
        {
          "fee_code": "usps_priority_mail_express",
          "fee_type": "service",
          "amount": 45.7
        }
      ]
    }
  },
  {
    "carrier": "usps",
    "service_type": "usps_media_mail",
    "packaging_type": "large_envelope",
    "estimated_delivery_days": "7",
    "estimated_delivery_date": "2021-09-13T21:30:14.226Z",
    "is_guaranteed_service": false,
    "trackable": "yes",
    "is_return_label": false,
    "is_customs_required": false,
    "shipment_cost": {
      "total_amount": 3.82,
      "currency": "usd",
      "cost_details": [
        {
          "fee_code": "usps_media_mail",
          "fee_type": "service",
          "amount": 3.82
        }
      ]
    }
  }
]

Creating a Label

As described in Viewing Shipping Rates, there are many options available for both domestic and international labels. Once a specific rate has been selected from these available options, the rate details can be included in the request to POST /labels in order to purchase the shipping label.

The following examples will cover both a simple domestic USPS shipping label using only the required and most common request settings, as well as an international label for a basic USPS First Class International shipment to Canada. There are many other ways to configure a label request, including advanced_options or different image formats and label layouts. For further details, see the Create a Label section in the reference guide.

Note that default values will be used for any optional elements omitted from a label creation request.

Create a Domestic Label

  1. Input sample domestic shipment details into the label generation request. The example provided can be used. For further details on this request, see the Create a Label section
  2. Notable request elements:
    • The from_address must contain the name or company_name, address_line1, city,state_province, and postal_code.
  3. After executing the sample request, a response should be returned containing an array of labels, each with an href field containing a URL. Fetch that URL in a browser to see the final shipping label.

Create an International Label

  1. Input sample international shipment details into the label generation request. The example provided can be used. For further details on this request, see the Create a Label section . This is very similar to domestic label creation, one of the main differences being the inclusion of Customs information in the customs object for international.3. Notable request elements:
    • The from_address must contain the name or company_name, address_line1, city,state_province, and postal_code.
    • The customs object contains a description of what is being shipped. International shipments require Customs information and will be submitted electronically to the carrier in addition to being printed with your label if required.
  2. After executing the sample request, a response should be returned containing an array of labels, each with an href field containing a URL. Fetch that URL in a browser to see the final shipping label.

Request

{
  "from_address": {
    "name": "Michael M",
    "address_line1": "1150 Magic Way",
    "city": "Anaheim",
    "state_province": "CA",
    "postal_code": "92802",
    "country_code": "US",
    "email": "[email protected]"
  },
  "to_address": {
    "name": "Minerva M",
    "address_line1": "351 S Studio Dr",
    "city": "Lake Buena Vista",
    "state_province": "FL",
    "postal_code": "32830",
    "country_code": "US",
    "email": "[email protected]"
  },
  "service_type": "usps_priority_mail",
  "package": {
    "packaging_type": "package",
    "weight": 4,
    "weight_unit": "ounce"
  },
  "ship_date": "2021-09-10",
  "is_test_label": true
}

Response

{
  "label_id": "13bab305-a5eb-4ad6-a1d2-e5b545e764fb",
  "tracking_number": "9405511899560772485630",
  "carrier": "usps",
  "service_type": "usps_priority_mail",
  "packaging_type": "package",
  "estimated_delivery_days": "2",
  "estimated_delivery_date": "2021-09-13T00:00:00",
  "is_guaranteed_service": false,
  "trackable": "yes",
  "is_return_label": false,
  "is_gap": false,
  "is_smartsaver": false,
  "is_etoe": false,
  "shipment_cost": {
    "total_amount": 8.8,
    "currency": "usd",
    "cost_details": [
      {
        "fee_code": "usps_priority_mail",
        "fee_type": "service",
        "amount": 8.8
      },
      {
        "fee_code": "tracking",
        "fee_type": "tracking",
        "amount": 0
      }
    ]
  },
  "account_balance": {
    "amount_available": 390.65,
    "max_balance_amount_allowed": 10000,
    "currency": "usd"
  },
  "labels": [
    {
      "href": "<LabelURL>"
    }
  ],
  "forms": null,
  "branding_id": null,
  "notification_setting_id": null
}

Cancelling a Label

If a user wishes to request a refund for any unused prepaid labels, the PUT /labels/{label_id}/void endpoint can be called to cancel the label. The carrier may need to verify that the label was not used in order to authorize the refund. As a result, it may take 2–3 weeks to approve a refund request.

To create a refund request, call the PUT /labels/{label_id}/void endpoint with a valid label_id (as returned in the original label's response) in the URL which represents the label to be cancelled. Pay-On-Use labels are not eligible to be cancelled.

Note that test labels created in the staging environment do not need to be cancelled and are printed with a visible "VOID" message over the label image.

Validate or Parse an Address

Sometimes an integration may need to explicitly request address validation. For example, there may be cases where SERA could not automatically validate the address during the label creation process. An address can be submitted to the POST /addresses/validate endpoint to perform this validation. The address validation results will then be returned along with any applicable candidate addresses. These candidate addresses can then be reviewed, and a correct address can be selected for use in shipping by the user or application.

It is best practice to fully validate addresses used for shipping in order to minimize package delivery issues. Note that a validated city, state, and postal code are required when shipping domestically.

Request

[
  {
    "address_line1": "4800 Third Ave",
    "city": "Kearney",
    "state_province": "NE",
    "postal_code": "68845",
    "country_code": "US",
    "email": null
  }
]

Response

[
  {
    "original_address": {
      "company_name": null,
      "name": null,
      "address_line1": "4800 Third Ave",
      "address_line2": null,
      "address_line3": null,
      "city": "Kearney",
      "state_province": "NE",
      "postal_code": "68845",
      "country_code": "US",
      "phone": null,
      "email": null,
      "residential_indicator": null,
      "formatted_address": null
    },
    "matched_address": {
      "company_name": null,
      "name": null,
      "address_line1": "4800 3RD AVE",
      "address_line2": "",
      "address_line3": null,
      "city": "KEARNEY",
      "state_province": "NE",
      "postal_code": "68845-2892",
      "country_code": "US",
      "phone": null,
      "email": null,
      "residential_indicator": "no",
      "formatted_address": "4800 3RD AVE\nKEARNEY, NE 68845-2892"
    },
    "candidate_addresses": [],
    "is_po_box": false,
    "is_apo_fpo": false,
    "validation_results": {
      "result_code": "V100",
      "result_description": "Full Address Verified.",
      "result_details": null
    }
  }
]

There may also be scenarios where an application needs to explicitly request address parsing, such as when only a freeform address string is provided. A freeform address string can be submitted to the POST /addresses/parse endpoint to parse it into a formatted address. The formatted address will then be returned along with the address fields the parser was able to populate. This parsed address can then be passed to the POST /addresses/validate endpoint to validate the address if needed.

Request

{
  "full_address": "Jeff Moreau 7700 W Parmer Ln Unit 250 Austin Tx 78729"
}

Response

{
  "company_name": null,
  "name": "Jeff Moreau",
  "address_line1": "7700 W Parmer Ln Unit 250",
  "address_line2": "",
  "address_line3": null,
  "city": "Austin",
  "state_province": "TX",
  "postal_code": "78729-8101",
  "country_code": "US",
  "phone": null,
  "email": null,
  "residential_indicator": null,
  "formatted_address": "7700 W Parmer Ln Unit 250\nAustin, TX 78729-8101"
}

Track a Package

After shipping a package, most integrators also need to periodically check on the status of a package. The GET /tracking endpoint returns tracking events for any shipment created through Stamps.com/Endicia. Include a label_id or tracking_number in the request to specify the label to track.

The response will consist of an array of tracking_event objects with timestamps for each event.

Authentication

In order to access SERA, integrations must call the API with a valid access token. Access tokens can be generated with a valid authorization code from a user's login event or with an refresh token from an earlier login. The endpoints below detail how to login to receive an authorization code and how to turn that code into a valid set of access and refresh tokens.

SERA (Production)

Security Scheme Type OAuth2
authorizationCode OAuth Flow

SERA (Staging)

Security Scheme Type OAuth2
authorizationCode OAuth Flow

Get Authorization Code

Integrators call this endpoint to receive a 302 redirect to a hosted HTML login page. Once the user completes the login page, they will be redirected to the URL specified in redirect_uri with an authorization code contained in the code query parameter. For example, if the redirect_uri is "https://www.stamps.com", the user will be directed to "https://www.stamps.com/?code=<AuthorizationCode>" on successful login. Use this authorization code to generate an access_token.

query Parameters
client_id
string

Client ID
Identifies the integrated application connecting to SERA

response_type
string
Value: "code"
Example: response_type=code

Response Type
Set to code for the authorization code flow

redirect_uri
string

Redirect URI
The login page will redirect to this URI on successful login

scope
string
Value: "offline_access"

Scope
Specify this scope value as offline_access in order to receive a refresh_token in the response

Responses

Get/Refresh Access Token

Integrators call this endpoint with a valid authorization code or refresh_token and use the access_token from the response to access SERA.

Request Body schema: application/json
One of
grant_type
required
string
Value: "authorization_code"

Grant Type
Must set to authorization_code for this request

client_id
required
string

Client ID
Identifies the integrated application connecting to SERA

client_secret
string

Client Secret
Used to securely validate the Client ID

code
string

Authorization Code

redirect_uri
string

Redirect URI
Used to generate Authorization Code. Must match the redirect_uri value used in the /authorize call.

Responses

Request samples

Content type
application/json
{
  • "grant_type": "refresh_token",
  • "client_id": "string",
  • "client_secret": "string",
  • "refresh_token": "string"
}

Response samples

Content type
application/json
{
  • "access_token": "string",
  • "refresh_token": "string",
  • "id_token": "string",
  • "token_type": "string",
  • "expires_in": "string"
}

Account Info

SERA labels and services are paid for with an account balance. Funds are added to the account balance from the account’s default payment method, while transaction amounts for labels and services are deducted from the account balance. While most customers utilize credit cards to fund their accounts balances, we do offer alternative payment methods such as ACH on request.

Most labels are deducted from the account balance at time of print. We also offer Pay-On-Use services (e.g. USPS Returns) that deduct from the account balance when the label is shipped instead of when it is created. New accounts are limited to a maximum balance of $500 which can be adjusted by contacting our customer care team.

Get Account Info

This endpoint will return account information associated with the active user account.

Authorizations:
SERA (Production)SERA (Staging)

Responses

Response samples

Content type
application/json
{
  • "account": {
    }
}

Get Current Account Balance

The current account balance can be checked by calling this endpoint with no request body. The response will contain the account’s current balance.

Authorizations:
SERA (Production)SERA (Staging)

Responses

Response samples

Content type
application/json
{
  • "amount_available": 0,
  • "max_balance_amount_allowed": 0,
  • "currency": "usd"
}

Add Funds to Account Balance

To add funds to the account balance, call this endpoint with the amount you wish to add in the request body. A successful response will contain the current balance on the account.

In the SERA production environment, adding funds to the account balance will charge the account’s default payment method. In contrast, funds added in the SERA staging environment will not cost anything; staging account balances are funded with "play money."

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
amount
number

Amount
The amount to add to the account balance

currency
string
Default: "usd"

Currency
The currency used for the amount

Responses

Request samples

Content type
application/json
{
  • "amount": 0,
  • "currency": "usd"
}

Response samples

Content type
application/json
{
  • "amount_available": 0,
  • "max_balance_amount_allowed": 0,
  • "currency": "usd"
}

Get Hosted URL

There are several account management operations that are available to Stamps.com/Endicia users. Rather than duplicate that functionality in the form of API access, creating an additional burden on integrators to create the interface for it, SERA allows the integrator to obtain the URL of Stamps.com/Endicia-hosted web pages to perform these operations. Call this endpoint with a specific url_type query parameter to receive the URL of the hosted page.

The URLs returned from this endpoint are specific to the user and session, allowing the web interface to display information tailored for the user without requiring the user to re-authenticate. The URL is only valid for one request, so the URL should be immediately navigated to in a browser and not stored by the integration.

URLs to the following Stamps.com web pages are available through this web method: Home, Account Settings, Edit Cost Codes, Online Reports, and Help.

Through special arrangement, the Stamps.com/Endicia-hosted pages may be co-branded for the integrator. When this is done, an optional query parameter, application_context, may be included to customize the appearance and behavior of the hosted web page.

Authorizations:
SERA (Production)SERA (Staging)
query Parameters
url_type
required
string
Enum: "home_page" "account_settings_page" "edit_cost_codes_page" "online_reports_page" "help_page" "online_reporting_history" "online_reporting_refund" "online_reporting_pickup" "online_reporting_scan" "online_reporting_claim" "store_change_plan" "web_client_home" "reports_balances" "reports_expenses" "reports_prints" "store_buy_postage" "store_meters" "store_users" "store_payment_methods" "store_corp_contact_info" "store_meter_users" "store_meter_settings" "store_meter_address" "store_shipping_addresses" "store_refer_a_friend" "store_account_credit" "store_reorder" "store_my_profile" "store_password" "store_comm_preferences" "store_netstamps_labels" "store_shipping_labels" "store_mailing_labels" "store_scales_and_printers" "store_free_usps_supplies" "store_bubble_mailers" "store_shipping_supplies" "store_scales" "store_avery_net_stamps_labels" "store_avery_mailing_labels" "store_meter_contact_info" "store_edit_meter_address" "store_home" "store_account" "store_cost_code" "store_history" "store_faq" "store_customer_home" "store_get_account_info_json" "store_set_account_info_json" "store_user_categories" "store_category" "store_update_payment_method_resubmit" "store_default_payment_methods" "store_sign_out" "custom_ship_notify_email" "help_center_home" "must_change_password" "contacts" "web_client_preferences" "web_client_default" "store_auto_buy" "set_terms_general" "upload_image" "endicia_login" "phone_verification" "carrier_setup_dhl_express" "carrier_setup_ups" "carrier_management" "store_order_history" "store_subscriptions" "store_hardware" "store_envelopes" "store_labels" "store_clear_netstamps" "store_original_netstamps" "store_netstamps" "store_sign_in" "add_payment" "carrier_setup_fedex" "parcelguard" "branded_tracking" "rate_advisor" "parcelguard_claim" "parcelguard_claim_status"

URL Type

application_context
string

Application Context
Through special arrangement with Stamps.com, the Stamps.com/Endicia-hosted web pages may be co-branded for the integrator. When this is done, an additional query parameter, application_context, can be set to control the behavior of the customized web page.

Responses

Response samples

Content type
application/json

Set Account Security Questions

Call this endpoint to set security questions for an account that doesn't have them. Call GET /v1/security_questions to see the full list of available security questions.

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
security_question1_type
required
string
security_question1_value
required
string [ 2 .. 33 ] characters
security_question2_type
required
string
security_question2_value
required
string [ 2 .. 33 ] characters

Responses

Request samples

Content type
application/json
{
  • "security_question1_type": "string",
  • "security_question1_value": "string",
  • "security_question2_type": "string",
  • "security_question2_value": "string"
}

Get Available Account Security Questions

Call this to see the full list of available security questions. To set security questions for an account that does not have them, call PUT /v1/account/security_questions

Authorizations:
SERA (Production)SERA (Staging)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Rates and Labels

View Shipping Rates

Rates contains all of a single shipment’s details, from origin and destination addresses to weight, carrier, and service options. Users can search for and compare different rates with calls to this SERA endpoint. In order to create a shipping label, a specific rate should be selected from the numerous available options and combinations.

This endpoint optionally accepts details about the shipment to narrow down the available rates. If available, add information such as the To and From addresses (or even just ZIP codes), along with package weight, type, and dimensions to the request body to receive a list of rates filtered for those attributes.

When searching for a specific rate, try to include as much information as possible in the initial request to receive a list of available rates more closely filtered to what is needed. If looking for a broad list of rates (for example, to populate a selection dialog), omit specific package information to receive an unfiltered list of available rates.

Using the response, it is up to the user or integration’s logic to select the desired rate. Once selected, the integration can use those rate details when creating a label. Rates will vary by carrier_code and service_code (such as "usps_priority_mail" for USPS Priority Mail) and may be further customized with any available advanced_options (such as Signature Confirmation or Insurance).

While testing, feel free to modify the example request to reflect various specific shipment details. Also, be sure to update the ship_date to a date that is not in the past or an error will be returned.

Authorizations:
SERA (Production)SERA (Staging)
query Parameters
carriers
string
Enum: "usps" "globalpost" "ups" "fedex" "dhl_express" "canada_post"
Request Body schema: application/json
object (address)
object (address)
service_type
string
Enum: "usps_first_class_mail" "usps_ground_advantage" "usps_priority_mail" "usps_priority_mail_express" "usps_parcel_select" "usps_media_mail" "usps_first_class_mail_international" "usps_priority_mail_international" "usps_priority_mail_express_international" "usps_pay_on_use_return" "globalpost_first_class_smartsaver" "globalpost_parcel_select_smartsaver" "globalpost_economy_international" "globalpost_economy_international_smartsaver" "globalpost_standard_international" "globalpost_standard_international_smartsaver" "globalpost_plus" "globalpost_plus_smartsaver" "globalpost_first_class_international" "globalpost_first_class_international_smartsaver" "globalpost_priority_mail__international_smartsaver" "globalpost_priority_mail_express_international" "globalpost_ priority_mail_express_international_smartsaver" "ups_next_day_air_early" "ups_next_day_air" "ups_next_day_air_saver" "ups_2nd_day_air_am" "ups_2nd_day_air" "ups_3_day_select" "ups_ground" "ups_standard" "ups_worldwide_express" "ups_worldwide_express_plus" "ups_worldwide_expedited" "ups_worldwide_saver" "fedex_first_overnight" "fedex_priority_overnight" "fedex_standard_overnight" "fedex_2day_am" "fedex_2day" "fedex_express_saver" "fedex_ground" "fedex_home_delivery" "fedex_international_first" "fedex_international_priority" "fedex_international_economy" "fedex_international_ground" "dhl_express_worldwide" "canada_post_regular_parcel" "canada_post_xpresspost" "canada_post_priority" "canada_post_expedited_parcel" "canada_post_small_packet_air_usa" "canada_post_tracked_packet_usa" "canada_post_expedited_parcel_usa" "canada_post_xpresspost_usa" "canada_post_priority_worldwide_usa" "canada_post_small_packet_international_surface" "canada_post_small_packet_international_air" "canada_post_international_parcel_surface" "canada_post_international_parcel_air" "canada_post_tracked_packet_international" "canada_post_xpresspost_international" "canada_post_priority_worldwide_international"

Service Type
Identifies the Carrier and Service used
Note: Not all carriers are enabled for every account. Please contact us to ensure a specific carrier is available and activated for your account.

object (package)

Package

delivery_confirmation_type
string
Enum: "none" "tracking" "signature" "adult_signature" "direct_signature" "delivery_confirmation_mailed"

Delivery Confirmation Type

object

Insurance

object (customs)

Customs Form

ship_date
string

Ship Date

is_return_label
boolean

Is Return Label

object (advanced_options)

Responses

Request samples

Content type
application/json
{
  • "from_address": {
    },
  • "to_address": {
    },
  • "service_type": "usps_first_class_mail",
  • "package": {
    },
  • "delivery_confirmation_type": "none",
  • "insurance": {
    },
  • "customs": {
    },
  • "ship_date": "string",
  • "is_return_label": true,
  • "advanced_options": {
    }
}

Response samples

Content type
application/json
[
  • {
    }
]

Create a Label

Once a specific rate is selected as described in View Shipping Rates, include the rate details in a request to this endpoint to purchase the shipping label.

For most labels, the rate amount will be deducted from the account balance when the label is created with this step. Be sure to have sufficient account balance for this before requesting the label or an error will be generated.

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
object (address)
object (address)
object (address)
service_type
string
Enum: "usps_first_class_mail" "usps_ground_advantage" "usps_priority_mail" "usps_priority_mail_express" "usps_parcel_select" "usps_media_mail" "usps_first_class_mail_international" "usps_priority_mail_international" "usps_priority_mail_express_international" "usps_pay_on_use_return" "globalpost_first_class_smartsaver" "globalpost_parcel_select_smartsaver" "globalpost_economy_international" "globalpost_economy_international_smartsaver" "globalpost_standard_international" "globalpost_standard_international_smartsaver" "globalpost_plus" "globalpost_plus_smartsaver" "globalpost_first_class_international" "globalpost_first_class_international_smartsaver" "globalpost_priority_mail__international_smartsaver" "globalpost_priority_mail_express_international" "globalpost_ priority_mail_express_international_smartsaver" "ups_next_day_air_early" "ups_next_day_air" "ups_next_day_air_saver" "ups_2nd_day_air_am" "ups_2nd_day_air" "ups_3_day_select" "ups_ground" "ups_standard" "ups_worldwide_express" "ups_worldwide_express_plus" "ups_worldwide_expedited" "ups_worldwide_saver" "fedex_first_overnight" "fedex_priority_overnight" "fedex_standard_overnight" "fedex_2day_am" "fedex_2day" "fedex_express_saver" "fedex_ground" "fedex_home_delivery" "fedex_international_first" "fedex_international_priority" "fedex_international_economy" "fedex_international_ground" "dhl_express_worldwide" "canada_post_regular_parcel" "canada_post_xpresspost" "canada_post_priority" "canada_post_expedited_parcel" "canada_post_small_packet_air_usa" "canada_post_tracked_packet_usa" "canada_post_expedited_parcel_usa" "canada_post_xpresspost_usa" "canada_post_priority_worldwide_usa" "canada_post_small_packet_international_surface" "canada_post_small_packet_international_air" "canada_post_international_parcel_surface" "canada_post_international_parcel_air" "canada_post_tracked_packet_international" "canada_post_xpresspost_international" "canada_post_priority_worldwide_international"

Service Type
Identifies the Carrier and Service used
Note: Not all carriers are enabled for every account. Please contact us to ensure a specific carrier is available and activated for your account.

object (package)

Package

delivery_confirmation_type
string
Enum: "none" "tracking" "signature" "adult_signature" "direct_signature" "delivery_confirmation_mailed"

Delivery Confirmation Type

object
object (customs)

Customs Form

ship_date
string

Ship Date

is_return_label
boolean

Is Return Label

object (advanced_options)
object (label_options)

Label Options

object

Email Label
Used to email the generated label

object
object
is_test_label
boolean
Default: false

Is Test Label
Set to true to generate a test/sample label with no account charge

Responses

Request samples

Content type
application/json
{
  • "from_address": {
    },
  • "return_address": {
    },
  • "to_address": {
    },
  • "service_type": "usps_first_class_mail",
  • "package": {
    },
  • "delivery_confirmation_type": "none",
  • "insurance": {
    },
  • "customs": {
    },
  • "ship_date": "string",
  • "is_return_label": true,
  • "advanced_options": {
    },
  • "label_options": {
    },
  • "email_label": {
    },
  • "references": {
    },
  • "order_details": {
    },
  • "is_test_label": false
}

Response samples

Content type
application/json
{
  • "label_id": "string",
  • "tracking_number": "string",
  • "carrier": "usps",
  • "service_type": "usps_first_class_mail",
  • "packaging_type": "large_envelope",
  • "estimated_delivery_days": "string",
  • "estimated_delivery_date": "string",
  • "is_guaranteed_service": true,
  • "trackable": "yes",
  • "is_return_label": true,
  • "is_gap": true,
  • "is_smartsaver": true,
  • "is_etoe": true,
  • "shipment_cost": {
    },
  • "account_balance": {
    },
  • "labels": [
    ],
  • "forms": [
    ]
}

Void a Label

Users must void unused prepaid labels to request a refund. The carrier may need to verify the label was not used in order to authorize a refund. As a result, it may take 2–3 weeks to approve a refund request once submitted.

To request a refund, call this endpoint with a valid label_id (as returned in the original label's response) in the URL to identify the label to cancel. Pay-On-Use labels are not eligible to be voided.

Authorizations:
SERA (Production)SERA (Staging)
path Parameters
label_id
required
string

Responses

Validate an Address

To help improve package deliverability, it is best practice to fully validate all addresses used while shipping. While it’s not required that users ship to fully-validated addresses, it is required that users ship to addresses with at least partial validation: a validated city, state, and postal code are required when shipping domestically.

Occasionally, if SERA cannot automatically validate an address while creating a shipping label, the integration may need to explicitly request address validation. To do this, submit the address to this endpoint.

In the response, SERA will return the address validation status along with any applicable candidate addresses. The user or application should review the candidate addresses and select one for use in shipping if it is correct.

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
Array
company_name
string

Company Name

name
string

Full Name

address_line1
string

Address Line 1

address_line2
string

Address Line 2

address_line3
string

Address Line 3

city
string

City

state_province
string

State/Province

postal_code
string

Postal/ZIP Code

country_code
string = 2 characters

Country Code
ISO 3166 alpha-2 Country Code

phone
string

Phone Number

email
string

Email Address

residential_indicator
string

Residential Indicator

formatted_address
string

Formatted Address

Responses

Request samples

Content type
application/json
[
  • {
    }
]

Response samples

Content type
application/json
[
  • {
    }
]

Reprint a Label

Call this endpoint with an existing label_id to request the label image or data of a previously-created label. This will allow for an application to implement reprint functionality. Users are allowed to specify new label options to make non-material modifications to the reprinted label.

API users are only allowed to reprint labels originally printed from their own user account.

⚠️ Integrations are required to call this reprint endpoint to retrieve a label image for a reprint request. Labels should not be stored client-side after the initial print.

Authorizations:
SERA (Production)SERA (Staging)
path Parameters
label_id
required
string

Label ID
The label_id of the original label

query Parameters
label_size
string
Enum: "4x6" "letter" "4x6.75-doctab" "4x8.25-doctab"

Label Size

label_format
string
Enum: "png" "pdf" "zpl" "zpl_ascii"

Label Format

label_output_type
string
Enum: "url" "base64"

Label Output Type
Specify url to request a URL to an image containing the label. Specify base64 to receive base64-encoded image data.

Responses

Response samples

Content type
application/json
{
  • "labels": [
    ],
  • "forms": [
    ]
}

Carrier Services

Create a Carrier Manifest or USPS SCAN form

Depending on the carrier, a printed manifest (also called a SCAN form for USPS) may be needed when shipping multiple packages at once. Users can generate a manifest one of two ways:

  1. Submit a from_address and ship_date. SERA will collect any matching prints to generate a manifest for.
  2. Submit a list of label_ids to generate a manifest for.

The response will contain URLs for printable manifests in the requested format.

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
One of
object (address)
carrier
string
Enum: "usps" "globalpost" "ups" "fedex" "dhl_express" "canada_post"

Carrier

ship_date
string

Ship Date to create a manifest for

object (manifest_label_options)

Responses

Request samples

Content type
application/json
{
  • "label_ids": [
    ],
  • "label_options": {
    }
}

Response samples

Content type
application/json
{
  • "manifest_id": "string",
  • "carrier": "usps",
  • "ship_date": "string",
  • "number_of_items_in_manifest": 0,
  • "labels": [
    ]
}

Request a Carrier Pickup

Carrier pickups can be scheduled by calling this endpoint with a carrier_code and a preferred pickup time.

The response will contain pickup_window information along with information about the pickup request.

Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
One of
object (address)
carrier
string
Enum: "usps" "globalpost" "ups" "fedex" "dhl_express" "canada_post"

Carrier

object

Pickup Window

pickup_instructions
string

Pickup Instructions

Responses

Request samples

Content type
application/json
{
  • "label_ids": [
    ],
  • "pickup_window": {
    },
  • "pickup_instructions": "Knock on door"
}

Response samples

Content type
application/json
{
  • "pickup_id": "string",
  • "carrier": "usps",
  • "pickup_window": {
    },
  • "number_of_items_in_pickup": 0,
  • "estimated_cost": {
    }
}

Cancel a Carrier Pickup

To cancel a carrier pickup, call this endpoint with the pickup_id in the URL. No request body is needed.

The status of your request will be returned in the response.

Authorizations:
SERA (Production)SERA (Staging)
path Parameters
pickup_id
required
string

Responses

Track a Package

After shipping a package, most integrators also need to periodically check on the status of a package. This endpoint retrieves and returns standardized tracking events for a given shipment. Include a valid carrier_code and tracking_number in the request’s query string to select the appropriate shipment.

The response will consist of the shipment’s current status and a full array of tracking_events with timestamps for each event. Because SERA standardizes carrier tracking for our supported carriers, integrators do not need to do any extra work to retrieve or interpret tracking status information on a carrier-by-carrier basis.

Authorizations:
SERA (Production)SERA (Staging)
query Parameters
carrier
string
tracking_number
string

Responses

Response samples

Content type
application/json
{
  • "tracking_number": "string",
  • "carrier_name": "string",
  • "status_code": "accepted",
  • "carrier_status_description": "string",
  • "estimated_delivery_date": "string",
  • "destination": {
    },
  • "tracking_events": [
    ]
}

Create a Container Label

Depending on the carrier and types of packages, a container label may be needed when shipping multiple packages at once in a container. Users can generate a container label two ways:

  1. Submit a from_address and ship_date. SERA will collect any matching prints to generate a container label for.
  2. Submit a list of label_ids to generate a container label for.
Authorizations:
SERA (Production)SERA (Staging)
Request Body schema: application/json
One of
object (address)
object (address)
ship_date
string
object (container_label_options)
number_of_container_labels
number

Responses

Request samples

Content type
application/json
{
  • "label_ids": "string",
  • "label_options": {
    },
  • "number_of_container_labels": 0
}

Response samples

Content type
application/json
{
  • "container_label_id": "string",
  • "tracking_numbers": [
    ],
  • "carrier": "usps",
  • "ship_date": "string",
  • "number_of_items_in_container_labels": 0,
  • "number_of_container_labels": 0,
  • "labels": [
    ]
}

Get All Available Carrier Services

As carrier service availability may vary based on user accounts, integrations may call this endpoint to receive a JSON object detailing the specific services and service limitations to present to users.

Authorizations:
SERA (Production)SERA (Staging)
query Parameters
ship_date
string <date>

An optional query parameter to customize the response to the services and rules available on a specific date

Responses

Response samples

Content type
application/json
{
  • "shipping_options": [
    ]
}

Connect a Carrier Account

Call this endpoint to connect your existing carrier account to SERA.

Authorizations:
SERA (Production)SERA (Staging)
path Parameters
carrier
required
string
Request Body schema: application/json
One of
user_owned_account
required
boolean
Default: true
username
required
string
password
required
string

Responses

Request samples

Content type
application/json
Example
{
  • "user_owned_account": true,
  • "username": "string",
  • "password": "string"
}

Disconnect a Carrier Account

Call this endpoint to disconnect your existing carrier account from SERA.

Authorizations:
SERA (Production)SERA (Staging)
path Parameters
carrier
required
string

Responses

address

company_name
string

Company Name

name
string

Full Name

address_line1
string

Address Line 1

address_line2
string

Address Line 2

address_line3
string

Address Line 3

city
string

City

state_province
string

State/Province

postal_code
string

Postal/ZIP Code

country_code
string = 2 characters

Country Code
ISO 3166 alpha-2 Country Code

phone
string

Phone Number

email
string

Email Address

residential_indicator
string

Residential Indicator

{
  • "company_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "address_line3": "string",
  • "city": "string",
  • "state_province": "string",
  • "postal_code": "string",
  • "country_code": "st",
  • "phone": "string",
  • "email": "string",
  • "residential_indicator": "string"
}

package

packaging_type
string
Default: "package"
Enum: "large_envelope" "package" "usps_small_flat_rate_box" "usps_medium_flat_rate_box" "usps_large_flat_rate_box" "usps_flat_rate_envelope" "usps_padded_flat_rate_envelope" "usps_legal_flat_rate_envelope" "usps_regional_rate_box_a" "usps_regional_rate_box_b" "ups_letter" "ups_pak" "ups_tube" "ups_express_box_small" "ups_express_box_medium" "ups_express_box_large" "ups_10kg_box" "ups_25kg_box" "fedex_envelope" "fedex_pak" "fedex_tube" "fedex_one_rate_envelope" "fedex_one_rate_pak" "fedex_one_rate_tube" "fedex_one_rate_small_box" "fedex_one_rate_medium_box" "fedex_one_rate_large_box" "fedex_one_rate_extra_large_box" "fedex_10kg_box" "fedex_25kg_box" "express_envelope" "canada_post_envelope" "canada_post_pak"

Packaging Type

weight
number

Weight

weight_unit
string
Default: "ounce"
Enum: "ounce" "pound" "gram" "kilogram"

Weight Unit
The units for the associated weight field

length
number

Length
The units for this field as set in the dimension_unit element

width
number

Width
The units for this field as set in the dimension_unit element

height
number

Height
The units for this field as set in the dimension_unit element

dimension_unit
string
Default: "inch"
Enum: "inch" "centimeter"

Dimension Unit
The units for the associated length, width, and height fields

{
  • "packaging_type": "large_envelope",
  • "weight": 0,
  • "weight_unit": "ounce",
  • "length": 0,
  • "width": 0,
  • "height": 0,
  • "dimension_unit": "inch"
}

label_options

label_size
string
Default: "4x6"
Enum: "4x6" "letter" "4x6.75-doctab" "4x8.25-doctab"

Label Size

label_format
string
Default: "pdf"
Enum: "png" "pdf" "zpl" "zpl_ascii"

Label Format

label_logo_image_id
integer
label_output_type
string
Default: "url"
Enum: "url" "base64"

Label Output Type
Specify url to request a URL to an image containing the label. Specify base64 to receive base64-encoded image data.

{
  • "label_size": "4x6",
  • "label_format": "png",
  • "label_logo_image_id": 0,
  • "label_output_type": "url"
}

advanced_options

non_machinable
boolean

Non-Machinable

saturday_delivery
boolean

Saturday Delivery

delivered_duty_paid
boolean

Delivered Duty Paid

hold_for_pickup
boolean

Hold for Pickup

certified_mail
boolean

Certified Mail

return_receipt
boolean

Return Receipt (Physical)

return_receipt_electronic
boolean

Return Receipt (Electronic)

object

Collect on Delivery (COD)

object

Registered Mail

sunday_delivery
boolean

Sunday Delivery

holiday_delivery
boolean

Holiday Delivery

restricted_delivery
boolean

Restricted Delivery

notice_of_non_delivery
boolean

Notice of Non-Delivery

object

Special Handling

object

No Label

is_pay_on_use
boolean

Is Pay-On-Use

object

Return Options

{
  • "non_machinable": true,
  • "saturday_delivery": true,
  • "delivered_duty_paid": true,
  • "hold_for_pickup": true,
  • "certified_mail": true,
  • "return_receipt": true,
  • "return_receipt_electronic": true,
  • "collect_on_delivery": {
    },
  • "registered_mail": {
    },
  • "sunday_delivery": true,
  • "holiday_delivery": true,
  • "restricted_delivery": true,
  • "notice_of_non_delivery": true,
  • "special_handling": {
    },
  • "no_label": {
    },
  • "is_pay_on_use": true,
  • "return_options": {
    }
}

customs

contents_type
string
Enum: "gift" "merchandise" "returned_goods" "documents" "sample" "other"

Contents Type

contents_description
string

Contents Description

non_delivery_option
string
Enum: "treat_as_abandoned" "return_to_sender"

Non-Delivery Option

object

Customs Sender Information

object

Customs Recipient Information

Array of objects

Customs Items Array

{
  • "contents_type": "gift",
  • "contents_description": "string",
  • "non_delivery_option": "treat_as_abandoned",
  • "sender_info": {
    },
  • "recipient_info": {
    },
  • "customs_items": [
    ]
}

Errors

CategoryHttpStatusCodeErrorCodeError Message TextNotes
Generic400800000(varies)Model validation error, message will vary depending on which part of the request model was invalid
Idempotency400800001Idempotency-Key provided was invalid.
Idempotency400800002Idempotency-Key header not found for enforced idempotent endpoint.
Label400800010The label_id specified is invalid
Pickups400800100Pickups are not supported for the carrier specified.
Pickups400800101The labels specified belong to more than one carrier.
Pickups400800102One or more labels specified cannot be included in a pickup.
Pickups400800103USPS pickups are not allowed on Sundays.
Pickups400800104USPS pickups are not allowed on holidays.
Pickups400800105USPS pickups must be scheduled for the following USPS business day.
Pickups400800106The labels for label_ids submitted must contain the same address and contact information.
Manifest400800200Manifests are not supported for the carrier specified.
Generic400899999(varies)Unexpected/Unhandled exception