YourBusiness.eBay.SDK
1.0.3
dotnet add package YourBusiness.eBay.SDK --version 1.0.3
NuGet\Install-Package YourBusiness.eBay.SDK -Version 1.0.3
<PackageReference Include="YourBusiness.eBay.SDK" Version="1.0.3" />
<PackageVersion Include="YourBusiness.eBay.SDK" Version="1.0.3" />
<PackageReference Include="YourBusiness.eBay.SDK" />
paket add YourBusiness.eBay.SDK --version 1.0.3
#r "nuget: YourBusiness.eBay.SDK, 1.0.3"
#:package YourBusiness.eBay.SDK@1.0.3
#addin nuget:?package=YourBusiness.eBay.SDK&version=1.0.3
#tool nuget:?package=YourBusiness.eBay.SDK&version=1.0.3
YourBusiness.eBay.SDK
A .NET 8 SDK for connecting your application to eBay's Inventory, Fulfillment, and Account APIs — built for Australian sellers (EBAY_AU) with full OAuth 2.0 support.
Installation
dotnet add package YourBusiness.eBay.SDK
Requirements
- .NET 8 or later
- An active eBay Developer Program account
- Sandbox or Production application keys
- A configured RuName (eBay Redirect URL Name)
- eBay Business Policies (Fulfillment, Payment, Return)
- A Merchant Location (Warehouse address)
1. Add Credentials to appsettings.json
{
"EbaySettings": {
"AppId": "your-app-id",
"DevId": "your-dev-id",
"CertId": "your-cert-id",
"RuName": "Your_Name-AppName-SBX-xxxxxxx-xxxxxxxx",
"RefreshToken": "",
"Environment": "sandbox",
"MarketplaceId": "EBAY_AU",
"MerchantLocationKey": "default",
"FulfillmentPolicyId": "your-fulfillment-policy-id",
"PaymentPolicyId": "your-payment-policy-id",
"ReturnPolicyId": "your-return-policy-id"
}
}
Where to find these values:
AppId,DevId,CertId→ eBay Developer Portal → Application KeysRuName→ Application Keys → User Tokens → Redirect URL NameRefreshToken→ Generated after completing the OAuth consent flow (see Step 4)MerchantLocationKey→ Set after callingPOST /api/product/setup/location- Policy IDs → Set after calling
POST /api/product/setup/policies
⚠️ Security: Never commit
appsettings.jsonto source control. Use environment variables or a secrets manager in production.
2. Register in Program.cs
using YourBusiness.eBay.SDK.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEbaySdk(builder.Configuration); // ← registers everything
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.Run();
3. Create Your Own Product Class
Extend EbayProduct and override MapToEbay() to map your own fields:
using YourBusiness.eBay.SDK.Models;
public class Product : EbayProduct
{
public int ProductId { get; set; }
public string Name { get; set; } = string.Empty;
public string RefCode { get; set; } = string.Empty;
public string ReferenceId { get; set; } = string.Empty;
public override void MapToEbay()
{
Title = Name;
EbaySku = RefCode; // ⚠️ SKU must be alphanumeric only — no hyphens or spaces
}
}
⚠️ SKU Rules: eBay only accepts alphanumeric SKUs — no hyphens, spaces or symbols.
❌ Rejected ✅ Accepted SKU-WH-001-BLKSKUWH001BLKSKU WH 001SKUWH001
4. OAuth Consent Flow (One-Time Setup)
This SDK uses eBay's Authorization Code Grant flow.
You must complete this once to generate a RefreshToken.
After that, tokens refresh silently and automatically.
Step 1 — Configure your RuName on eBay Developer Portal
1. Go to https://developer.ebay.com → Application Keys → User Tokens
2. Under your RuName, fill in:
- Display Title → Your App Name
- Privacy Policy URL → https://your-domain.com
- Auth Accepted URL → https://your-domain.com/ebay/callback
- Auth Declined URL → https://your-domain.com/ebay/callback
3. Select the "OAuth" radio button → Save
For local development, eBay requires a public HTTPS URL. Use ngrok to expose localhost:
ngrok http https://localhost:7182 --host-header="localhost:7182"Use the generated
https://xxxx.ngrok-free.appURL in the eBay portal fields.
Step 2 — Add the OAuth Controller to Your API Project
using Microsoft.AspNetCore.Mvc;
using YourBusiness.eBay.SDK.Services;
[ApiController]
[Route("ebay")]
public class EbayOAuthController : ControllerBase
{
private readonly IEbayService _ebayService;
private readonly ILogger<EbayOAuthController> _logger;
public EbayOAuthController(
IEbayService ebayService,
ILogger<EbayOAuthController> logger)
{
_ebayService = ebayService;
_logger = logger;
}
// Step 1: Open this in your browser
// GET /ebay/connect
[HttpGet("connect")]
public IActionResult Connect()
{
var consentUrl = _ebayService.GetConsentUrl();
_logger.LogInformation("Redirecting to eBay consent: {Url}", consentUrl);
return Redirect(consentUrl);
}
// Step 2: eBay redirects here after the user clicks Agree
// GET /ebay/callback?code=xxx
[HttpGet("callback")]
public async Task<IActionResult> Callback(
[FromQuery] string? code,
[FromQuery] string? error)
{
if (!string.IsNullOrEmpty(error))
return BadRequest($"eBay consent declined: {error}");
if (string.IsNullOrEmpty(code))
return BadRequest("Authorization code missing.");
await _ebayService.ExchangeAuthCodeAsync(code);
return Ok(new
{
message = "eBay connected. Copy RefreshToken into appsettings.json.",
refreshToken = _ebayService.CurrentRefreshToken
});
}
}
Step 3 — Complete the Flow
1. Run your app
2. Open browser → https://your-app/ebay/connect
3. Log in with your eBay Sandbox test user account
4. Click "Agree" on the permissions page
5. Copy the refreshToken from the JSON response
6. Paste it into appsettings.json → "RefreshToken": "v^1.1#i^1..."
7. Restart your app
⚠️ The authorization code eBay returns expires in 299 seconds (5 minutes). Exchange it immediately by visiting
/ebay/callback?code=...
⚠️ If you add new OAuth scopes later, you must clear the
RefreshTokenand redo this flow — existing tokens do not gain new scopes automatically.
From this point forward, the SDK silently refreshes tokens automatically.
5. First-Time Setup (Run Once After OAuth)
After completing OAuth, run these setup endpoints once in order:
Step 1 — Check Opted-In Programs
GET /api/product/setup/programs
Expected response:
{ "programs": "{\"programs\":[{\"programType\":\"SELLING_POLICY_MANAGEMENT\"}]}" }
If SELLING_POLICY_MANAGEMENT is not listed, call:
POST /api/product/setup/optin
Step 2 — Create Merchant Location
POST /api/product/setup/location
Creates a warehouse address required by eBay to publish offers.
Response:
{
"message": "Merchant location created successfully.",
"locationKey": "default",
"nextStep": "Now call POST /api/product/setup/policies"
}
Step 3 — Create Business Policies
POST /api/product/setup/policies
Creates Fulfillment, Payment, and Return policies automatically.
Response:
{
"message": "All policies created. Copy these into appsettings.json.",
"ids": "FulfillmentPolicyId: 123 | PaymentPolicyId: 456 | ReturnPolicyId: 789"
}
Paste the three IDs into appsettings.json then restart your app.
If policies already exist from a previous attempt, use:
GET /api/product/setup/fetch-policiesto retrieve the existing IDs without creating duplicates.
6. Available Services
All methods are available via IEbayService:
public class ProductController : ControllerBase
{
private readonly IEbayService _ebay;
public ProductController(IEbayService ebay)
=> _ebay = ebay;
}
Create a Listing
Creates the inventory item and publishes it as a live eBay listing in a single call (3 eBay API calls internally).
var product = new Product
{
ProductId = 1,
Name = "Wireless Headphones",
RefCode = "SKUWH001BLK", // alphanumeric only — no hyphens
Price = 79.99m,
Quantity = 50,
Brand = "YourBrand",
MPN = "WH001", // required if Brand is set
Model = "WH001", // required by most categories
CategoryId = "112529",
Description = "High quality wireless headphones with noise cancellation.",
ImageUrls = new() { "https://yoursite.com.au/img/headphones.jpg" },
// Required item specifics — use British spelling for EBAY_AU
Aspects = new Dictionary<string, string[]>
{
{ "Model", new[] { "WH001" } },
{ "Brand", new[] { "YourBrand" } },
{ "Connectivity", new[] { "Wireless" } },
{ "Type", new[] { "Headphones" } },
{ "Colour", new[] { "Black" } }, // ← British spelling
{ "Form Factor", new[] { "Over-Ear" } },
}
};
EbayResult result = await _ebay.CreateListingAsync(product);
// result.Success → true / false
// result.ErrorMessage → eBay error details if failed
Publish an Existing Offer
If an inventory item already exists but was never published:
// Must call MapToEbay() first so EbaySku is set correctly
product.MapToEbay();
EbayResult result = await _ebay.PublishOfferAsync(product);
Update a Listing
EbayResult result = await _ebay.UpdateListingAsync(product);
Delete a Listing
bool success = await _ebay.DeleteListingAsync("SKUWH001BLK");
Get a Single Listing
EbayProduct? product = await _ebay.GetListingAsync("SKUWH001BLK");
Get All Inventory Items
Returns all items in your eBay inventory (created but not necessarily live):
List<EbayProduct> products = await _ebay.GetAllListingsAsync();
Get All Published Offers
Returns all live listings with their offer ID, status, listing ID and price:
List<EbayOffer> offers = await _ebay.GetAllOffersAsync();
// offer.OfferId
// offer.Sku
// offer.Status
// offer.Listing.ListingId
// offer.PricingSummary.Price.Value
Update Inventory Quantity
bool success = await _ebay.UpdateInventoryAsync("SKUWH001BLK", quantity: 25);
Update Price
bool success = await _ebay.UpdatePriceAsync("SKUWH001BLK", newPrice: 89.99m);
Get Orders
// Last 7 days by default
List<EbayOrder> orders = await _ebay.GetOrdersAsync();
// Or specify a date
List<EbayOrder> orders = await _ebay.GetOrdersAsync(
fromDate: DateTime.UtcNow.AddDays(-30));
Acknowledge an Order
bool success = await _ebay.AcknowledgeOrderAsync("order-id-here");
Get Business Policy IDs
EbayPolicies policies = await _ebay.GetPoliciesAsync();
// policies.FulfillmentPolicyId
// policies.PaymentPolicyId
// policies.ReturnPolicyId
7. Item Specifics (Aspects)
eBay requires category-specific item attributes called aspects. Missing aspects will cause listing publication to fail.
Aspects = new Dictionary<string, string[]>
{
{ "Model", new[] { "WH001" } },
{ "Brand", new[] { "MyBrand" } },
{ "Connectivity", new[] { "Wireless" } },
{ "Colour", new[] { "Black" } }, // ← British spelling for EBAY_AU
}
Important spelling rules for EBAY_AU:
❌ American ✅ Australian Color Colour Flavor Flavour Fiber Fibre Aluminum Aluminium
To find all required aspects for any category, call the eBay Taxonomy API:
GET https://api.ebay.com/commerce/taxonomy/v1/category_tree/15/get_item_aspects_for_category?category_id={categoryId}
Brand and MPN rules:
- If
Brandis set,MPNmust also be set (and vice versa)- If neither is set, both are safely omitted from the payload
- Mixing one without the other causes eBay to reject the listing
8. EbayResult Model
CreateListingAsync, UpdateListingAsync and PublishOfferAsync return EbayResult:
public class EbayResult
{
public bool Success { get; init; }
public string? ErrorMessage { get; init; }
public string? PolicyId { get; init; } // returned by setup methods
}
Usage:
var result = await _ebay.CreateListingAsync(product);
if (result.Success)
return Ok("Listed on eBay");
else
return BadRequest(result.ErrorMessage);
9. OAuth Token Lifecycle
| Token Type | Lifespan | Usage |
|---|---|---|
| Access Token | 2 hours | Authorizes every API request |
| Refresh Token | ~18 months | Silently mints new access tokens |
The SDK handles token expiry and refresh automatically.
You only need to store the RefreshToken in appsettings.json.
10. How Listing Publication Works
eBay's Inventory API requires three internal steps to publish a live listing.
CreateListingAsync handles all three automatically:
1. PUT /sell/inventory/v1/inventory_item/{sku} Creates the item
↓
2. POST /sell/inventory/v1/offer Creates an offer
↓
3. POST /sell/inventory/v1/offer/{offerId}/publish Makes it live
If the offer already exists from a previous attempt, the SDK automatically retrieves and updates it before publishing.
11. Full Setup Order (First Time)
1. Fill in AppId, DevId, CertId, RuName in appsettings.json
2. Configure RuName on eBay Developer Portal
(set Auth Accepted URL + Auth Declined URL → your /ebay/callback)
3. Run your app
4. GET /ebay/connect → complete OAuth consent flow
Copy RefreshToken → paste into appsettings.json → restart app
5. GET /api/product/setup/programs → verify account is opted in
6. POST /api/product/setup/location → create merchant warehouse location
7. POST /api/product/setup/policies → create Fulfillment, Payment, Return policies
Copy the 3 policy IDs → paste into appsettings.json → restart app
8. POST /api/product/push → create and publish your first listing ✅
9. GET /api/product/offers → verify listing is live ✅
12. All API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/ebay/connect |
Start OAuth consent flow |
GET |
/ebay/callback |
OAuth callback (eBay redirects here) |
POST |
/api/product/push |
Create + publish listing |
PUT |
/api/product/update |
Update existing listing |
DELETE |
/api/product/delete/{sku} |
Delete a listing |
GET |
/api/product/{sku} |
Get a single inventory item |
GET |
/api/product/all |
Get all inventory items |
GET |
/api/product/offers |
Get all published offers |
POST |
/api/product/publish/{sku} |
Publish an existing offer |
PATCH |
/api/product/inventory/{sku} |
Update stock quantity |
PATCH |
/api/product/price/{sku} |
Update price |
GET |
/api/product/orders |
Get recent orders |
POST |
/api/product/orders/{id}/acknowledge |
Acknowledge an order |
GET |
/api/product/policies |
Get current policy IDs from eBay |
GET |
/api/product/setup/programs |
Check opted-in programs |
POST |
/api/product/setup/optin |
Opt into Business Policy Management |
POST |
/api/product/setup/location |
Create merchant warehouse location |
POST |
/api/product/setup/policies |
Create all business policies |
GET |
/api/product/setup/fetch-policies |
Fetch existing policy IDs |
13. Environments
| Setting | Sandbox | Production |
|---|---|---|
Environment |
"sandbox" |
"production" |
| Token URL | api.sandbox.ebay.com | api.ebay.com |
| Consent URL | auth.sandbox.ebay.com | auth.ebay.com |
| OAuth Scopes | Always api.ebay.com |
Same |
14. OAuth Scopes Used
https://api.ebay.com/oauth/api_scope
https://api.ebay.com/oauth/api_scope/sell.inventory
https://api.ebay.com/oauth/api_scope/sell.fulfillment
https://api.ebay.com/oauth/api_scope/sell.account
Scopes always reference
api.ebay.com— neverapi.sandbox.ebay.com.
15. Rate Limits
| Grant Type | Limit |
|---|---|
| client_credentials | 1,000 / day |
| authorization_code | 10,000 / day |
| refresh_token | 50,000 / day |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- System.Text.Json (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.