Stuck on integration? Have a question? The developer is standing by.
POST /v2/track

Track parcels (billable)

Overview

Track up to 5 parcels at once. Average response time 5 seconds per item. Supports 500+ carriers including USPS, UPS, FedEx, DHL, and more.

When to use this endpoint: Use /v2/track for on-demand, one-off lookups — for example, when a customer checks their order status on your website.

For continuous monitoring, use Webhooks instead. If you need to keep your database in sync with delivery status (e.g., updating order records, triggering notifications), register a webhook subscription via /v2/webhooks/register with recurring: true. The webhook approach is far more efficient — instead of polling repeatedly, you receive a push notification only when the status actually changes.

Rate Limits: Each API key has per-minute and per-month request quotas based on your plan. When exceeded, the API returns HTTP 429. See response headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset for current usage.

Plan Requests/min Requests/month
Free 1 5
Starter 30 10,000
Pro 60 30,000
Business 200 300,000

Example Request

// npm install whereparcel
import { WhereParcel } from 'whereparcel';

const wp = new WhereParcel('wp_test_public_demo_key_do_not_use_in_production', 'sk_test_public_demo_secret_do_not_use_in_production');

const response = await wp.trackBulk([
  {
    "carrier": "kr.cj",
    "trackingNumber": "123456789012"
  },
  {
    "carrier": "de.gls",
    "trackingNumber": "48117308687"
  }
]);

console.log(response.summary);
for (const result of response.results) {
  if (result.status === 'success') {
    console.log(result.data.deliveryStatus);
  }
}
curl -X POST https://api.whereparcel.com/v2/track \
  -H "Authorization: Bearer wp_test_public_demo_key_do_not_use_in_production:sk_test_public_demo_secret_do_not_use_in_production" \
  -H "Content-Type: application/json" \
  -d '{
    "trackingItems": [
      {
        "carrier": "kr.cj",
        "trackingNumber": "123456789012"
      },
      {
        "carrier": "de.gls",
        "trackingNumber": "48117308687",
        "postalCode": "04179"
      }
    ]
  }'
const response = await fetch('https://api.whereparcel.com/v2/track', {
  method: 'POST',
  headers: {
    "Authorization": "Bearer wp_test_public_demo_key_do_not_use_in_production:sk_test_public_demo_secret_do_not_use_in_production",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
      "trackingItems": [
        {
          "carrier": "kr.cj",
          "trackingNumber": "123456789012"
        },
        {
          "carrier": "de.gls",
          "trackingNumber": "48117308687",
          "postalCode": "04179"
        }
      ]
    })
});

const data = await response.json();
console.log(data);
<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.whereparcel.com/v2/track');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');

$headers = [
  'Authorization: Bearer wp_test_public_demo_key_do_not_use_in_production:sk_test_public_demo_secret_do_not_use_in_production',
  'Content-Type: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$data = [
  'trackingItems' => [
    '0' => [
      'carrier' => "kr.cj",
      'trackingNumber' => "123456789012"
    ],
    '1' => [
      'carrier' => "de.gls",
      'trackingNumber' => "48117308687",
      'postalCode' => "04179"
    ]
  ]
];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
print_r($result);
import requests
import json

url = 'https://api.whereparcel.com/v2/track'

headers = {
    'Authorization': 'Bearer wp_test_public_demo_key_do_not_use_in_production:sk_test_public_demo_secret_do_not_use_in_production',
    'Content-Type': 'application/json'
}

data = {
    'trackingItems': {
        '0': {
            'carrier': "kr.cj",
            'trackingNumber': "123456789012"
        },
        '1': {
            'carrier': "de.gls",
            'trackingNumber': "48117308687",
            'postalCode': "04179"
        }
    }
}

response = requests.post(url, headers=headers, json=data)

result = response.json()
print(result)
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.whereparcel.com/v2/track"

	payload := []byte(`{"trackingItems":[{"carrier":"kr.cj","trackingNumber":"123456789012"},{"carrier":"de.gls","trackingNumber":"48117308687","postalCode":"04179"}]}`)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))

	req.Header.Add("Authorization", "Bearer wp_test_public_demo_key_do_not_use_in_production:sk_test_public_demo_secret_do_not_use_in_production")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
💡 Note: Replace the test API key with your actual API key from the dashboard.

Request Body

Name Type Required Description
trackingItems array Required
trackingItems[].carrier string Required
Carrier code (e.g., 'kr.cj', 'us.fedex', 'de.gls')
trackingItems[].trackingNumber string Required
Tracking number
trackingItems[].clientId string Optional
Client tracking ID (returned as-is in the response)
trackingItems[].postalCode string Optional
Postal code (required/optional for some carriers, e.g., GLS Germany)
trackingItems[].phoneNumber string Optional
Phone number (required/optional for some carriers)

Response

Success Response (200)

200 OK

Successful tracking response

Response Body

{
  "success": true,
  "results": [
    {
      "carrier": "kr.cj",
      "trackingNumber": "123456789012",
      "clientId": "order-123",
      "success": true,
      "data": {
        "carrier": "kr.cj",
        "carrierName": "CJ대한통운",
        "trackingNumber": "123456789012",
        "status": "delivered",
        "statusText": "배달완료",
        "events": [
          {
            "timestamp": "2026-02-05T14:30:00+09:00",
            "status": "delivered",
            "statusText": "배달완료",
            "location": "서울 강남구",
            "description": "고객님께 배달이 완료되었습니다"
          },
          {
            "timestamp": "2026-02-05T09:15:00+09:00",
            "status": "out_for_delivery",
            "statusText": "배달 출발",
            "location": "서울 강남구 센터"
          },
          {
            "timestamp": "2026-02-04T18:00:00+09:00",
            "status": "in_transit",
            "statusText": "집하",
            "location": "서울 송파구 센터"
          }
        ]
      }
    },
    {
      "carrier": "kr.hanjin",
      "trackingNumber": "987654321098",
      "success": true,
      "data": {
        "carrier": "kr.hanjin",
        "carrierName": "한진택배",
        "trackingNumber": "987654321098",
        "status": "in_transit",
        "statusText": "배송 중",
        "events": [
          {
            "timestamp": "2026-02-05T12:00:00+09:00",
            "status": "in_transit",
            "statusText": "간선상차",
            "location": "경기 성남시"
          }
        ]
      }
    }
  ]
}

Error Response (401)

401 Unauthorized

Authentication failed - API key missing or invalid

Response Body

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key"
  }
}

Error Response (429)

429 Too Many Requests

Rate limit exceeded

Response Body

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please try again later."
  }
}
Got a question? Just ask.

Drop by our Discord — the developer behind WhereParcel reads every message and replies personally. No bots, no tickets, just a real conversation.