NAV
elixir shell

Introduction

Welcome to the ScriptDrop Tracking API.

Tracking API v1 lets callers subscribe to shipment tracking updates for a USPS or UPS tracking number. When a subscription is enabled, ScriptDrop posts notification events to the caller's listener_url as tracking status changes.

Use the subscription endpoints to enable tracking, check subscription status, and receive webhook notifications at your listener URL.

Base URLs

Environment Base URL
Production https://request.scriptdrop.co/tracking/v1/subscriptions
Sandbox https://request.sandbox.scriptdrop.co/tracking/v1/subscriptions

The examples below use the production base URL. Substitute the sandbox URL when testing against the sandbox environment.

Authentication

Authentication uses HTTP Basic authentication.

The API key is sent as the Basic auth username. The API secret is sent as the Basic auth password.

To authorize, use this code:

api_key = "pk_myapikey1234"
api_secret = "sk_myapisecret1234"

encoded_authorization = Base.encode64("#{api_key}:#{api_secret}")

authorization_header = "Basic #{encoded_authorization}"
export SCRIPTDROP_API_KEY="pk_myapikey1234"
export SCRIPTDROP_API_SECRET="sk_myapisecret1234"

ScriptDrop uses API keys to allow access to the API. Please contact our support team for API keys.

ScriptDrop expects API requests to include an Authorization header:

Authorization: Basic encoded_authorization

Authorization

Callers need active ScriptDrop API credentials that are explicitly enabled for Tracking API access.

Credentials issued for another ScriptDrop API surface are not automatically authorized for the Tracking API.

V1 Subscriptions

Tracking API v1 supports USPS and UPS tracking numbers. Subscription responses and notification events include "carrier": "USPS" or "carrier": "UPS".

Get a Subscription

url = "https://request.scriptdrop.co/tracking/v1/subscriptions"

headers = [
  {"Authorization", "Basic encoded_authorization"},
  {"Content-Type", "application/json"}
]

params = %{
  "tracking_number" => "9400111899223197428490"
}

HTTPoison.start()
HTTPoison.get!(url, headers, params: params)
curl --request GET \
  "https://request.scriptdrop.co/tracking/v1/subscriptions?tracking_number=9400111899223197428490" \
  --user "$SCRIPTDROP_API_KEY:$SCRIPTDROP_API_SECRET"

The above command returns JSON structured like this:

{
  "reference_id": "order-12345",
  "tracking_number": "9400111899223197428490",
  "carrier": "USPS",
  "subscription_status": "ENABLED",
  "subscription_status_reason": null,
  "subscribed_at": "2026-07-01T14:30:00Z",
  "updated_at": "2026-07-02T09:15:00Z"
}

Endpoint

GET https://request.scriptdrop.co/tracking/v1/subscriptions

Request Shape

Send tracking_number as a query parameter. Subscriptions are looked up by tracking number only.

Request Fields

Field Type Required Description
tracking_number string yes USPS or UPS tracking number to look up.

Response Fields

Field Type Description
reference_id string Caller-supplied metadata stored with the subscription. Echoed in the response; not used to filter GET requests.
tracking_number string USPS or UPS tracking number.
carrier string USPS or UPS in v1.
subscription_status string Current subscription status. See Subscription Status.
subscription_status_reason string Additional detail about the current status, when available.
subscribed_at string ISO 8601 timestamp when the subscription was created.
updated_at string ISO 8601 timestamp when the subscription was last updated.

Create or Update a Subscription

url = "https://request.scriptdrop.co/tracking/v1/subscriptions"

headers = [
  {"Authorization", "Basic encoded_authorization"},
  {"Content-Type", "application/json"}
]

subscription_params = %{
  "reference_id" => "order-12345",
  "tracking_number" => "9400111899223197428490",
  "listener_url" => "https://example.com/tracking/notifications"
}

HTTPoison.start()
HTTPoison.post(url, Jason.encode!(subscription_params), headers)
curl --request POST "https://request.scriptdrop.co/tracking/v1/subscriptions" \
  --user "$SCRIPTDROP_API_KEY:$SCRIPTDROP_API_SECRET" \
  --header "Content-Type: application/json" \
  --data '{
    "reference_id": "order-12345",
    "tracking_number": "9400111899223197428490",
    "listener_url": "https://example.com/tracking/notifications"
  }'

The above command returns JSON structured like this:

{
  "reference_id": "order-12345",
  "tracking_number": "9400111899223197428490",
  "carrier": "USPS",
  "subscription_status": "ENABLED",
  "subscription_status_reason": null,
  "subscribed_at": "2026-07-01T14:30:00Z",
  "updated_at": "2026-07-02T09:15:00Z"
}

Endpoint

POST https://request.scriptdrop.co/tracking/v1/subscriptions

Request Fields

Field Type Required Description
tracking_number string yes USPS or UPS tracking number to subscribe to.
listener_url string yes HTTPS URL where ScriptDrop posts tracking notification events.
reference_id string no Caller-supplied reference for the shipment.

Response Fields

Field Type Description
reference_id string Caller-supplied reference, if provided.
tracking_number string USPS or UPS tracking number.
carrier string USPS or UPS in v1.
subscription_status string Current subscription status. See Subscription Status.
subscription_status_reason string Additional detail about the current status, when available.
subscribed_at string ISO 8601 timestamp when the subscription was created.
updated_at string ISO 8601 timestamp when the subscription was last updated.

Subscription Status

ScriptDrop posts notifications to the supplied listener_url when a subscription is enabled. If the listener_url cannot be reached or is invalid, ScriptDrop changes the subscription status to SUSPENDED.

Status Description
ENABLED The subscription is active and notifications are sent to listener_url.
DISABLED A previously enabled subscription has ended.
SUSPENDED Notifications could not be delivered to listener_url.

Notification Events

When tracking status changes for an enabled subscription, ScriptDrop sends an HTTP POST request to the subscription's listener_url.

Notification Payload

{
  "reference_id": "order-12345",
  "tracking_number": "9400111899223197428490",
  "timestamp": "2026-07-02T09:15:00Z",
  "carrier": "USPS",
  "status": "Moving Through Network",
  "status_text": "Your package is moving through the carrier network.",
  "status_occurred_at": "2026-07-02T08:45:00Z",
  "tracking_events": [
    {
      "status": "Accepted",
      "status_occurred_at": "2026-07-01T14:30:00Z"
    },
    {
      "status": "Moving Through Network",
      "status_occurred_at": "2026-07-02T08:45:00Z"
    }
  ]
}

Notification Fields

Field Type Required Description
reference_id string no Caller-supplied reference, if provided.
tracking_number string yes USPS or UPS tracking number.
timestamp string yes ISO 8601 timestamp when the notification was generated.
carrier string yes USPS or UPS in v1.
status string yes Status category for the current tracking state.
status_text string no Customer-facing sentence summarizing the current status.
status_occurred_at string yes ISO 8601 timestamp when the current status occurred.
tracking_events array no Chronological tracking events for the shipment.
tracking_events[].status string no Status category for the event.
tracking_events[].status_occurred_at string no ISO 8601 timestamp when the event occurred.

Status Categories

Tracking status values use carrier-agnostic status categories such as:

Error Responses

Error responses return a JSON object with an error field containing a machine-readable code and a human-readable message.

Response Shape

{
  "error": {
    "code": "invalid_request",
    "message": "tracking_number is required"
  }
}
Field Type Description
error object Error details.
error.code string Machine-readable error code.
error.message string Human-readable description of the error.

The ScriptDrop Tracking API uses the following HTTP status codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is missing or invalid.
403 Forbidden -- Your API key is valid, but it is not enabled for Tracking API access.
404 Not Found -- The specified resource could not be found.
405 Method Not Allowed -- You tried to access a route that's not allowed.
406 Not Acceptable -- You requested a format that isn't supported.
429 Too Many Requests -- You've hit your request limit. Retry in a few moments.
500 Internal Server Error -- We had a problem with our server. Try again later.
502 Bad Gateway -- ScriptDrop could not retrieve a reliable status from an upstream provider.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

400 Bad Request

Your request is invalid.

Examples:

{
  "error": {
    "code": "invalid_request",
    "message": "tracking_number is required"
  }
}
{
  "error": {
    "code": "invalid_request",
    "message": "Request body must be valid JSON"
  }
}
{
  "error": {
    "code": "invalid_request",
    "message": "tracking_number must be a string"
  }
}
{
  "error": {
    "code": "invalid_request",
    "message": "Content-Type must be application/json"
  }
}

401 Unauthorized

Your API key is missing or invalid.

Examples:

{
  "error": {
    "code": "unauthorized",
    "message": "Authorization header is required"
  }
}
{
  "error": {
    "code": "unauthorized",
    "message": "Authorization scheme must be Basic"
  }
}
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid authorization credentials"
  }
}
{
  "error": {
    "code": "unauthorized",
    "message": "API key is invalid"
  }
}
{
  "error": {
    "code": "unauthorized",
    "message": "API secret is invalid"
  }
}
{
  "error": {
    "code": "unauthorized",
    "message": "API credentials are disabled"
  }
}

403 Forbidden

Your API key is valid, but it is not enabled for Tracking API access.

{
  "error": {
    "code": "forbidden",
    "message": "API credentials are not enabled for Tracking API access"
  }
}

404 Not Found

The specified resource could not be found.

{
  "error": {
    "code": "not_found",
    "message": "Subscription not found"
  }
}

405 Method Not Allowed

You tried to access a route that's not allowed.

{
  "error": {
    "code": "method_not_allowed",
    "message": "PATCH is not allowed on /tracking/v1/subscriptions"
  }
}

406 Not Acceptable

You requested a format that isn't supported.

{
  "error": {
    "code": "not_acceptable",
    "message": "Accept header must be application/json"
  }
}

429 Too Many Requests

You've hit your request limit. Retry in a few moments.

When available, the response includes a Retry-After header.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Retry after 60 seconds."
  }
}

500 Internal Server Error

We had a problem with our server. Try again later.

{
  "error": {
    "code": "internal_error",
    "message": "An unexpected error occurred"
  }
}

502 Bad Gateway

ScriptDrop could not retrieve a reliable status from an upstream provider.

{
  "error": {
    "code": "bad_gateway",
    "message": "Unable to subscribe to tracking number via upstream provider"
  }
}

503 Service Unavailable

We're temporarily offline for maintenance. Please try again later.

{
  "error": {
    "code": "service_unavailable",
    "message": "Service is temporarily unavailable. Please try again later."
  }
}