TL;DR
eBay APIs let you manage inventory, listings, orders, and payments on a global marketplace. Authenticate with OAuth 2.0, call api.ebay.com/sell endpoints, and handle rate limits carefully. Use Apidog to validate listing payloads, test order processing, and verify that your integration handles API limits gracefully.
Introduction
eBay APIs let sellers automate inventory management, create listings in bulk, process orders, handle shipping, and manage returns. The core implementation flow is:
- Create an eBay developer application.
- Complete OAuth 2.0 authorization.
- Create inventory locations and SKU-based inventory items.
- Create and publish offers.
- Poll orders and submit fulfillment details.
- Handle returns, token refreshes, and rate limits.
Main API areas
- Inventory API — Manage product inventory.
- Listing API — Create and manage item listings.
- Order API — Process orders and shipments.
- Fulfillment API — Handle shipping and tracking.
- Analytics API — Pull sales reports.
💡 If you’re building eBay integrations, Apidog helps you test listing creation, validate order responses, and verify rate-limit and error handling.
Test eBay APIs with Apidog - free
By the end of this guide, you will be able to:
- Authenticate with eBay OAuth 2.0.
- Create and manage inventory.
- Publish listings.
- Process orders and shipments.
- Handle returns and refunds.
- Test API workflows with Apidog.
Authentication with OAuth 2.0
eBay uses OAuth 2.0 for API authentication. Start by creating an application in the eBay Developers Program.
Create an application
- Go to
developers.ebay.com. - Sign up for a developer account.
- Create an application in the Developer Console.
- Copy your App ID (client ID) and Cert ID (client secret).
Store credentials in environment variables rather than committing them to source control:
export EBAY_APP_ID="your_app_id"
export EBAY_CERT_ID="your_cert_id"
export EBAY_REDIRECT_URI="your_signin_redirect_uri"
OAuth flow
Step 1: Redirect the user for authorization
https://auth.ebay.com/oauth2/authorize?
client_id=YOUR_APP_ID&
response_type=code&
redirect_uri=YOUR_SIGNIN_REDIRECT_URI&
scope=https://api.ebay.com/oauth/api_scope/sell.inventory
Step 2: Receive the authorization code
After the user authorizes your application, eBay redirects to your configured redirect URI with an authorization code.
Step 3: Exchange the code for tokens
const response = await fetch(
'https://api.ebay.com/identity/v1/oauth2/token',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization:
'Basic ' +
Buffer.from(`${APP_ID}:${CERT_ID}`).toString('base64'),
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: AUTHORIZATION_CODE,
redirect_uri: 'YOUR_SIGNIN_REDIRECT_URI',
}),
}
)
const { access_token, refresh_token, expires_in } = await response.json()
Persist the refresh token securely. Access tokens expire, so your integration should refresh them before making production API calls.
Required scopes
| Scope | Purpose |
|---|---|
https://api.ebay.com/oauth/api_scope/sell.inventory |
Inventory management |
https://api.ebay.com/oauth/api_scope/sell.listings |
Listings |
https://api.ebay.com/oauth/api_scope/sell.orders |
Orders |
https://api.ebay.com/oauth/api_scope/sell.fulfillment |
Fulfillment |
https://api.ebay.com/oauth/api_scope/sell.account |
Account management |
Inventory management
Inventory represents the products you sell. Use a stable SKU strategy because offers and order line items reference SKUs.
Create an inventory location
curl -X POST "https://api.ebay.com/sell/inventory/v1/location_inventory_location" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"locationId": "WAREHOUSE_1",
"name": "Main Warehouse",
"address": {
"addressLine1": "123 Main St",
"city": "San Jose",
"stateOrProvince": "CA",
"postalCode": "95101",
"countryCode": "US"
}
}'
Create an inventory item
Create an item before creating an offer for that SKU.
curl -X POST "https://api.ebay.com/sell/inventory/v1/inventory_item" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"product": {
"title": "Vintage Leather Messenger Bag",
"description": "Genuine leather messenger bag, perfect for work or school.",
"aspects": {
"Brand": ["Vintage"],
"Material": ["Leather"],
"Color": ["Brown"]
},
"imageUrls": [
"https://example.com/images/bag1.jpg",
"https://example.com/images/bag2.jpg"
]
},
"condition": "USED_GOOD",
"conditionNotes": "Minor wear on corners",
"availability": {
"shipToLocationAvailability": {
"quantity": 25
}
}
}'
Update inventory
Update availability when stock changes on eBay or another sales channel.
curl -X PUT "https://api.ebay.com/sell/inventory/v1/inventory_item/SKU123" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"availability": {
"shipToLocationAvailability": {
"quantity": 30
}
}
}'
Get an inventory item
curl -X GET "https://api.ebay.com/sell/inventory/v1/inventory_item/SKU123" \
-H "Authorization: Bearer ACCESS_TOKEN"
Listing items
An inventory item stores product data. An offer connects that SKU to a marketplace with price, listing, payment, and fulfillment details.
Create an offer
curl -X POST "https://api.ebay.com/sell/inventory/v1/offer" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sku": "SKU123",
"marketplaceId": "EBAY_US",
"format": "FIXED_PRICE",
"product": {
"title": "Vintage Leather Messenger Bag"
},
"pricingSummary": {
"price": {
"currency": "USD",
"value": "89.99"
}
},
"listing": {
"listingDuration": "GTC",
"listingType": "CLASSIC"
},
"fulfillment": {
"shippingProfileId": "SHIPPING_PROFILE_ID",
"fulfillmentPolicyId": "FULFILLMENT_POLICY_ID",
"paymentPolicyId": "PAYMENT_POLICY_ID"
}
}'
Key fields:
-
sku— Your inventory SKU. -
marketplaceId— For example,EBAY_US,EBAY_UK, orEBAY_DE. -
format—FIXED_PRICEorAUCTION. -
listingDuration— Listing duration;GTCmeans good til canceled. -
price— Your asking price.
Publish the offer
Create the offer first, then publish it using the returned offer ID.
curl -X POST "https://api.ebay.com/sell/inventory/v1/offer/OFFER_ID/publish" \
-H "Authorization: Bearer ACCESS_TOKEN"
Withdraw a listing
curl -X POST "https://api.ebay.com/sell/inventory/v1/offer/OFFER_ID/withdraw" \
-H "Authorization: Bearer ACCESS_TOKEN"
Order management
Use the Fulfillment API to retrieve orders, inspect line items, and get shipping instructions.
Get orders
curl -X GET "https://api.ebay.com/sell/fulfillment/v1/order?orderIds=ORDER_ID_1,ORDER_ID_2" \
-H "Authorization: Bearer ACCESS_TOKEN"
Filter orders by creation date:
curl -X GET "https://api.ebay.com/sell/fulfillment/v1/order?filter=creation_date_range:from:2026-01-01T00:00:00Z,to:2026-03-24T00:00:00Z" \
-H "Authorization: Bearer ACCESS_TOKEN"
Get order details
curl -X GET "https://api.ebay.com/sell/fulfillment/v1/order/ORDER_ID" \
-H "Authorization: Bearer ACCESS_TOKEN"
Example order response:
{
"orderId": "12-34567-89012",
"orderPaymentStatus": "PAID",
"pricingSummary": {
"total": {
"currency": "USD",
"value": "94.99"
}
},
"fulfillmentStartInstructions": [
{
"shippingStep": {
"shipTo": {
"fullName": "John Doe",
"contactAddress": {
"addressLine1": "123 Main St",
"city": "Anytown",
"stateOrProvince": "CA",
"postalCode": "12345",
"countryCode": "US"
}
}
}
}
],
"lineItems": [
{
"lineItemId": "LINE_ITEM_ID",
"sku": "SKU123",
"quantity": 1,
"title": "Vintage Leather Messenger Bag",
"lineItemCost": {
"currency": "USD",
"value": "89.99"
}
}
]
}
In your order-processing job, validate the payment status, iterate over lineItems, reserve inventory, and use fulfillmentStartInstructions to build shipment data.
Shipping and fulfillment
After shipping an order, submit carrier, shipping method, tracking number, and fulfilled line items.
Create shipping fulfillment
curl -X POST "https://api.ebay.com/sell/fulfillment/v1/order/ORDER_ID/shipping_fulfillment" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"lineItems": [
{
"lineItemId": "LINE_ITEM_ID",
"quantity": 1
}
],
"shippingStep": {
"shipFrom": {
"fullName": "Your Name",
"companyName": "Your Company",
"contactAddress": {
"addressLine1": "456 Warehouse Rd",
"city": "San Jose",
"stateOrProvince": "CA",
"postalCode": "95101",
"countryCode": "US"
}
}
},
"shippingCarrierCode": "USPS",
"shippingMethodCode": "PRIORITY_MAIL",
"trackingNumber": "9400111899223056789012"
}'
Supported carrier examples:
- USPS
- UPS
- FedEx
- DHL
Returns management
Get return details
curl -X GET "https://api.ebay.com/sell/fulfillment/v1/return/RETURN_ID" \
-H "Authorization: Bearer ACCESS_TOKEN"
Process a return
curl -X POST "https://api.ebay.com/sell/fulfillment/v1/return/RETURN_ID/decide" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"decision": "ACCEPT",
"shipment": {
"carrierId": "CARRIER_ID",
"trackingNumber": "TRACKING_NUMBER"
}
}'
Rate limits and error handling
eBay limits API calls to prevent abuse. Inspect rate-limit response headers on every request:
-
X-RateLimit-Limit— Maximum allowed requests. -
X-RateLimit-Remaining— Requests remaining in the current window. -
X-RateLimit-Reset— Unix timestamp when the limit resets.
Implement retries for 429 Too Many Requests responses:
async function makeEbayRequest(url, options, retries = 3) {
for (let i = 0; i < retries; i++) {
const response = await fetch(url, options)
const remaining = response.headers.get('X-RateLimit-Remaining')
if (remaining && parseInt(remaining, 10) < 10) {
console.warn('Rate limit low:', remaining)
}
if (response.status === 429) {
const resetTime = response.headers.get('X-RateLimit-Reset')
const waitTime = (parseInt(resetTime, 10) - Date.now() / 1000) * 1000
await sleep(waitTime)
continue
}
return response
}
throw new Error('Rate limited')
}
Use this wrapper for inventory updates, offer publishing, order polling, and fulfillment requests.
Testing with Apidog
eBay APIs are production-critical. Test request payloads and response handling before making live changes.
1. Configure an environment
Create an environment with these variables:
EBAY_APP_ID: your_app_id
EBAY_CERT_ID: your_cert_id
EBAY_ACCESS_TOKEN: stored_token
EBAY_REFRESH_TOKEN: stored_refresh
EBAY_MARKETPLACE_ID: EBAY_US
BASE_URL: https://api.ebay.com
Use {{BASE_URL}} and {{EBAY_ACCESS_TOKEN}} in request URLs and authorization headers so you can switch tokens or environments without editing every request.
2. Validate listing payloads
Add pre-request or test scripts to catch invalid offer payloads before sending them:
pm.test('Listing has required fields', () => {
const requestBody = JSON.parse(pm.request.body.raw)
pm.expect(requestBody).to.have.property('sku')
pm.expect(requestBody).to.have.property('marketplaceId')
pm.expect(requestBody.pricingSummary).to.have.property('price')
})
pm.test('Price is valid', () => {
const requestBody = JSON.parse(pm.request.body.raw)
const price = parseFloat(requestBody.pricingSummary.price.value)
pm.expect(price).to.be.above(0)
})
3. Test order processing
Validate the expected order structure before integrating it with fulfillment or inventory systems:
pm.test('Order response is valid', () => {
const response = pm.response.json()
pm.expect(response).to.have.property('orderId')
pm.expect(response.orderPaymentStatus).to.eql('PAID')
pm.expect(response.lineItems).to.be.an('array')
})
Test eBay APIs with Apidog - free
Common errors and fixes
401 Unauthorized
Cause: Token expired or is invalid.
Fix: Exchange the stored refresh token for a new access token.
const response = await fetch(
'https://api.ebay.com/identity/v1/oauth2/token',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization:
'Basic ' +
Buffer.from(`${APP_ID}:${CERT_ID}`).toString('base64'),
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: storedRefreshToken,
}),
}
)
10002: API error — Invalid access token
Cause: The access token expired.
Fix: Refresh the token immediately, then retry the request.
21916684: Item does not exist
Cause: You are trying to update a SKU that was not created.
Fix: Create the inventory item first, then create the offer.
10003: Invalid SKU
Cause: The SKU format is invalid.
Fix: SKUs must be unique within your inventory and can contain only alphanumeric characters, hyphens, and underscores.
Rate limit: 429
Cause: Too many requests.
Fix: Implement backoff and retry behavior. eBay limits vary by API and endpoint.
Alternatives and comparisons
| Feature | eBay | Amazon SP-API | Etsy |
|---|---|---|---|
| Inventory API | ✓ | ✓ | Limited |
| Listing API | ✓ | ✓ | ✓ |
| Order API | ✓ | ✓ | ✓ |
| Fulfillment API | ✓ | ✓ | Limited |
| Free tier | Developer program | Limited | Limited |
| API complexity | Medium | High | Low |
eBay’s API is more approachable than Amazon’s but less feature-rich. Etsy is simpler but more limited for larger sellers.
Real-world use cases
Multi-channel selling
A seller lists on eBay, Amazon, and their own site. Inventory syncs across platforms. When an item sells on one channel, quantity decrements everywhere.
Automated repricing
A seller monitors competitors and adjusts prices via API. When a competitor lowers prices, the seller’s prices adjust automatically to stay competitive.
Bulk listing
A seller with 10,000 items creates listings in bulk. The API accepts CSV uploads, creating thousands of listings automatically.
Conclusion
You now have the core workflow for an eBay seller integration:
- Authenticate with OAuth 2.0 using app credentials.
- Manage inventory with SKUs.
- Create and publish listings.
- Process orders and submit shipment information.
- Handle returns.
- Test with Apidog before going live.
Next steps
- Apply for the eBay Developers Program.
- Create an application and get credentials.
- Implement the OAuth flow.
- Create your first inventory item.
- Create and publish a test listing.
- Add token refresh and rate-limit handling before production.
Test eBay APIs with Apidog - free
FAQ
Do I need a business account to use APIs?
Yes. eBay APIs are for verified sellers. Sign up for a seller account and complete verification.
What’s the difference between inventory and offers?
Inventory stores product information such as title, description, and images. Offers link inventory to a marketplace with pricing and fulfillment information. Multiple offers can reference the same inventory.
How long do listings stay active?
Listings with GTC (good til canceled) stay active until you withdraw them or the item sells out.
Can I sell internationally via API?
Yes. Set marketplaceId to different values such as EBAY_US, EBAY_UK, or EBAY_DE. You must comply with each marketplace’s requirements.
What’s the API rate limit?
Limits vary by endpoint and account level. Check response headers for current limits.
How do I get shipping labels?
eBay provides discounted shipping labels through the Fulfillment API. You create the shipment and eBay generates a label.


Top comments (0)