PHP SDK for eBay API. Supports Trading API (XML) and Commerce API (REST), OAuth 2.0 authentication, 20+ marketplaces. Works as standalone and with Laravel.
- Features
- Requirements
- Installation
- Quick Start
- Authentication
- Trading API
- Commerce API
- Message API
- Working with Marketplaces
- Enums and DTOs
- Error Handling
- Optimization
- Testing
- FAQ
- Support
- License
API:
- Trading API (XML) — orders, listings, categories, GetMyEbaySelling, etc.
- Commerce API (REST) — inventory, fulfillment, taxonomy, translation
- Message API (REST) — buyer-seller messaging, conversations, notifications
- OAuth 2.0 with automatic token refresh
- 20+ marketplaces (US, UK, DE, FR, AU, etc.)
Code:
- PHP 8.1+ with native Enums
- Strict typing
- Immutable DTOs
- Fluent interface
- PSR-4, PSR-7, PSR-12
Laravel:
- Service Provider + Facade
- Dependency Injection
- .env configuration
- PHP 8.1+
- Guzzle 7.x
- Laravel 9.x / 10.x / 11.x / 12.x (optional)
- Composer
composer require tigusigalpa/ebay-phpFor Laravel — publish config:
php artisan vendor:publish --tag=ebay-configAdd credentials to .env:
EBAY_ENVIRONMENT=sandbox
# Sandbox
EBAY_SANDBOX_APP_ID=your-sandbox-app-id
EBAY_SANDBOX_CERT_ID=your-sandbox-cert-id
EBAY_SANDBOX_DEV_ID=your-sandbox-dev-id
EBAY_SANDBOX_RUNAME=your-sandbox-runame
# Production
EBAY_PRODUCTION_APP_ID=your-production-app-id
EBAY_PRODUCTION_CERT_ID=your-production-cert-id
EBAY_PRODUCTION_DEV_ID=your-production-dev-id
EBAY_PRODUCTION_RUNAME=your-production-runame
EBAY_DEFAULT_SITE=USGet credentials at eBay Developers Program.
use Tigusigalpa\Ebay\Facades\Ebay;
use Tigusigalpa\Ebay\Enums\Site;
// OAuth URL
$url = Ebay::getConsentUrl();
// Exchange code for tokens
$tokens = Ebay::exchangeCodeForToken($code);
// Get orders
$orders = Ebay::trading()->getOrders([
'CreateTimeFrom' => now()->subDays(30)->toIso8601String(),
]);
// Switch marketplace
Ebay::setSite(Site::UK)->trading()->getOrders();require_once 'vendor/autoload.php';
use Tigusigalpa\Ebay\Ebay;
use Tigusigalpa\Ebay\Enums\Site;
$ebay = new Ebay([
'environment' => 'sandbox',
'sandbox' => [
'app_id' => 'your-app-id',
'cert_id' => 'your-cert-id',
'dev_id' => 'your-dev-id',
'runame' => 'your-runame',
],
'site' => Site::US,
]);
$orders = $ebay->trading()->getOrders();1. Get authorization URL:
$consentUrl = Ebay::getConsentUrl(
scopes: config('ebay.scopes'),
state: 'your-state-parameter',
locale: 'en-US'
);
return redirect($consentUrl);2. Handle callback:
public function callback(Request $request)
{
$code = $request->get('code');
$tokenData = Ebay::exchangeCodeForToken($code);
// Store tokens
auth()->user()->update([
'ebay_access_token' => $tokenData['access_token'],
'ebay_access_token_expires_at' => $tokenData['expires_at'],
'ebay_refresh_token' => $tokenData['refresh_token'],
'ebay_refresh_token_expires_at' => $tokenData['refresh_token_expires_at'],
]);
return redirect()->route('dashboard');
}3. Use tokens:
$user = auth()->user();
Ebay::setAccessToken($user->ebay_access_token, $user->ebay_access_token_expires_at);
Ebay::setRefreshToken($user->ebay_refresh_token, $user->ebay_refresh_token_expires_at);
// Tokens refresh automatically when expired
$orders = Ebay::trading()->getOrders();$xml = Ebay::trading()->getOrders([
'CreateTimeFrom' => '2024-01-01T00:00:00.000Z',
'CreateTimeTo' => '2024-12-31T23:59:59.999Z',
'OrderStatus' => 'Active',
]);
foreach ($xml->OrderArray->Order as $order) {
$orderId = (string) $order->OrderID;
$total = (float) $order->Total;
}// Get item
$item = Ebay::trading()->getItem('123456789');
$title = (string) $item->Item->Title;
$price = (float) $item->Item->SellingStatus->CurrentPrice;
// Create listing
$response = Ebay::trading()->addFixedPriceItem([
'Title' => 'My Product Title',
'Description' => 'Product description',
'PrimaryCategory' => ['CategoryID' => '12345'],
'StartPrice' => 99.99,
'Quantity' => 10,
'Currency' => 'USD',
'Country' => 'US',
'Location' => 'New York',
'DispatchTimeMax' => 3,
'ShippingDetails' => [
'ShippingType' => 'Flat',
'ShippingServiceOptions' => [
'ShippingService' => 'USPSPriority',
'ShippingServiceCost' => 5.00,
],
],
]);
$itemId = (string) $response->ItemID;$categories = Ebay::trading()->getCategories([
'CategorySiteID' => 0,
'LevelLimit' => 2,
]);// Get
$item = Ebay::commerce()->getInventoryItem('SKU-123');
// Update quantity
Ebay::commerce()->createOrReplaceInventoryItem($sku, [
'availability' => ['shipToLocationAvailability' => ['quantity' => $newQuantity]],
]);$orders = Ebay::commerce()->getFulfillmentOrders([
'filter' => 'orderfulfillmentstatus:{NOT_STARTED|IN_PROGRESS}',
'limit' => 50,
]);$translated = Ebay::commerce()->translate(
text: 'Brand New iPhone',
fromLanguage: 'en',
toLanguage: 'de',
context: 'ITEM_TITLE'
);$aspects = Ebay::commerce()->getItemAspectsForCategory('0', '12345');
foreach ($aspects['aspects'] as $aspect) {
echo $aspect['localizedAspectName'];
}use Tigusigalpa\Ebay\Enums\{ConversationType, ConversationStatus};
$result = Ebay::message()->getConversations([
'conversation_type' => ConversationType::FROM_MEMBERS->value,
'conversation_status' => ConversationStatus::UNREAD->value,
'limit' => 25,
]);
foreach ($result['conversations'] as $conversation) {
echo $conversation->conversationTitle;
echo $conversation->latestMessage?->messageBody;
}// Start new conversation
$message = Ebay::message()->sendMessage([
'otherPartyUsername' => 'buyer_username',
'messageText' => 'Thank you for your question.',
'reference' => [
'referenceId' => '123456789',
'referenceType' => 'LISTING',
],
]);
// Reply to conversation
$message = Ebay::message()->sendMessage([
'conversationId' => 'c1234567890',
'messageText' => 'Here is the information you requested.',
]);// Mark as read
Ebay::message()->updateConversation([
'conversationId' => 'c1234567890',
'conversationType' => ConversationType::FROM_MEMBERS->value,
'read' => true,
]);
// Archive multiple conversations
$result = Ebay::message()->bulkUpdateConversation([
'conversations' => [
[
'conversationId' => 'c1111111111',
'conversationType' => ConversationType::FROM_MEMBERS->value,
'conversationStatus' => 'ARCHIVE',
],
],
]);use Tigusigalpa\Ebay\Enums\Site;
// Set marketplace
Ebay::setSite(Site::UK);
Ebay::setSite(Site::GERMANY);
Ebay::setSite(Site::AUSTRALIA);
// Marketplace information
$site = Site::US;
$site->title(); // "United States"
$site->code(); // "us"
$site->url(); // "https://ebay.com"
$site->locale(); // "en-US"
$site->marketplace(); // "EBAY_US"
$site->currency()->symbol(); // "$"
// Find by code
$site = Site::fromCode('uk'); // Site::UK
$site = Site::fromMarketplace('EBAY_DE'); // Site::GERMANY
// List on multiple marketplaces
foreach ([Site::UK, Site::GERMANY, Site::FRANCE] as $site) {
Ebay::setSite($site)->trading()->addFixedPriceItem($itemData);
}Package uses PHP 8.1 Enums for type safety:
use Tigusigalpa\Ebay\Enums\{Site, Currency, ListingStatus, OrderStatus, PaymentStatus, ListingType};
// Currency
$currency = Currency::USD;
$currency->symbol(); // "$"
$currency->htmlEntity(); // "$"
$currency->title(); // "US Dollar"
// Listing Status
$status = ListingStatus::ACTIVE;
$status->title(); // "Active"
$status->description();
// Listing Type
$listingType = ListingType::FIXED_PRICE;
$listingType->description(); // "Buy It Now format with a fixed price"use Tigusigalpa\Ebay\Http\Resources\{Order, Item};
$xml = Ebay::trading()->getOrders();
foreach ($xml->OrderArray->Order as $orderXml) {
$order = Order::fromXml($orderXml);
echo $order->orderId;
echo $order->total;
echo $order->orderStatus->title();
}
// Convert to array
$array = $order->toArray();use Tigusigalpa\Ebay\Exceptions\{EbayApiException, AuthenticationException, InvalidConfigurationException};
try {
$orders = Ebay::trading()->getOrders();
} catch (AuthenticationException $e) {
Log::error('eBay auth failed', [
'error_code' => $e->getErrorCode(),
'message' => $e->getMessage(),
]);
} catch (EbayApiException $e) {
foreach ($e->getErrors() as $error) {
echo $error['code'] . ': ' . $error['message'];
}
} catch (InvalidConfigurationException $e) {
Log::error('Invalid eBay configuration', ['message' => $e->getMessage()]);
}// config/ebay.php
'cache' => [
'enabled' => true,
'ttl' => 3600,
],RateLimiter::attempt('ebay-api', $perMinute = 5000, function() {
// API calls
});dispatch(new SyncEbayOrdersJob($dateRange));
dispatch(new UpdateInventoryJob($products));$itemIds = ['123', '456', '789'];
foreach ($itemIds as $itemId) {
$items[] = Ebay::trading()->getItem($itemId);
usleep(100000); // Rate limiting
}composer test
# Unit tests only
./vendor/bin/phpunit tests/Unit
# Feature tests only
./vendor/bin/phpunit tests/FeatureHow to get API credentials?
Register at eBay Developers Program, create application and get App ID, Cert ID, Dev ID, RuName.
Can I use for dropshipping?
Yes. Package is suitable for order automation, inventory, and listings.
What's the difference between Trading API and Commerce API?
- Trading API (XML) — legacy API for core operations (listings, orders, categories)
- Commerce API (REST) — modern REST API for inventory, fulfillment, and new features
How to switch to production?
Set EBAY_ENVIRONMENT=production in .env and add production credentials.
How to handle rate limits?
Use Laravel Rate Limiter or add usleep() between requests.
"Missing required configuration"
Check that all credentials are set in .env:
EBAY_SANDBOX_APP_ID=your-app-id
EBAY_SANDBOX_CERT_ID=your-cert-id
EBAY_SANDBOX_DEV_ID=your-dev-id
EBAY_SANDBOX_RUNAME=your-runameOAuth token expired
Package refreshes tokens automatically. Ensure refresh token is set:
Ebay::setRefreshToken($refreshToken, $expiresAt);XML parsing errors
Enable logging in config/ebay.php:
'logging' => ['enabled' => true],- Wiki: Documentation & Guides
- GitHub Issues: tigusigalpa/ebay-php/issues
- Discussions: GitHub Discussions
- Email: sovletig@gmail.com
git clone https://github.com/tigusigalpa/ebay-php.git
cd ebay-php
composer install
composer test
composer check-styleRequirements:
- PSR-12
- Tests for new features
- PHPDoc with links to eBay API docs
- Strict typing
MIT. See LICENSE.
Igor Sazonov
- GitHub: @tigusigalpa
- Email: sovletig@gmail.com
See CHANGELOG.md.
