If this repo helps you out then why not give it a star. I'll appreciate.
BricklinkSharp is a strongly-typed, easy-to-use C# client for the bricklink marketplace that gets you started with just a few lines of code. It features OAuth1 authentication, error handling and parsing of JSON data into typed instances. It supports all .NET platforms compatible with .NET standard 2.0.
- RebrickableSharp - Easy-to-use C# client for the Rebrickable (LEGO) API.
ℹ️ At the moment the project is assumed to be complete, nevertheless it will continue to be actively maintained to fix bugs and respond to API changes. If you encounter bugs or have suggestions for additional features then you can simply open an issue or submit a pull request.
- Updated System.Text.Json NuGet dependency to v8.0.4 for .netstandard targets, see https://github.com/advisories/GHSA-hh2w-p6rv-4g7w
- Added methods to retrieve thumbnail images from catalog items (see Retrieve thumbnail image url), thanks to stephanstapel
- Fixed GetPartOutValueFromPageAsync for >$1k sets returns just thousands as single digit, thanks to norberto5
- Added order.store_name to GetOrderAsync response, thanks to stephanstapel
- Added the option to inject a custom
IBricklinkRequestHandler
to handle the Bricklink API rate limiting (5000 requests per day) in your own way, thanks to stephanstapel
- Added order.date_status_changed to GetOrderAsync response, thanks to norberto5
- Added shipping.address.phone_number to GetOrderAsync response
- Added optional parameter
BricklinkCredentials? credentials = null
to every method onIBricklinkClient
that requires authentication. This will take precedence over the global credentials (BricklinkClientConfiguration.Instance
) and is useful for server scenarios (e.g. ASP.NET Core) where you need to do a request in the name of the logged in user - Fixed Exception updating inventory items, thanks to stephanstapel
- Improved
ItemTypeStringConverter
to fail on unknown strings (instead of returningItemType.Minifig
as default)
- Fixed GetPriceGuideAsync does not support the 'vat' parameter, thanks to cleargreen
- Added .NET7 Build Target
- Fixed UpdatePaymentStatusAsync expects wrong HTTP status code, thanks to Fandermill
⚠️ This version contains a typo fix which might have breaking behavior and requires a renaming of an Enum.
- Fixed a typo in RatingTargetRole (previous RatingTargeRole without "t") which has breaking behavior when using it.
- Fixed also property name RatingTargetRole in class Feedback.
- Fixed Error with EnumExtensions along with many performance improvements, thanks to xramcire
- Refactored all .cs files to use File Scoped Namespaces.
- Added CancellationToken support for all async methods.
- Fixed GetElementIdAsync throws an exception if no element ID is available. The method now instead returns an empty array.
- Fixed a typo in JsonPropertyName of the UpdateInventory.StockRoomId property that made it impossible for users to update the stock room ID, thanks to JelleCeulemans (bricklink store).
- Upgraded Demos and Tests to .NET6
- Added .NET6 Build Target
- Fixed all obsolete warnings for .NET6
- Minor performance improvements
- Removed unused code
- Fixed Get Supersets does not use color id, just gets all supersets, thanks to Yoonwoo.
- Supports API key for Exchange rate service when using the Get Part Out Value From Page method with the exchange rate service (see demo project and documentation on this readme below for usage)
- Covers all public API endpoints
- New Assembly versioning:
- Assembly Version: 1.0.0.0
- Assembly File Version: 1.0.0.<build ID>
- Assembly Informational File Version: 1.0.0-<build time>+<build date>
- Get Part Out Value From Page
- Demo project
- Docs
- Exchange rate service
- New method on IBricklinkClient: GetBookImage. Builds and returns the image URL for a specific book number
- New method on IBricklinkClient: GetGearImage. Builds and returns the image URL for a specific gear number
- New method on IBricklinkClient: GetCatalogImage. Builds and returns the image URL for a specific catalog number
- New method on IBricklinkClient: GetInstructionImage. Builds and returns the image URL for a specific instruction number
- New method on IBricklinkClient: GetOriginalBoxImage. Builds and returns the image URL for a specific original box number
- New method on IBricklinkClient: GetMinifigImage. Builds and returns the image URL for a specific minifigure number.
- New method on IBricklinkClient: GetSetImage. Builds and returns the image URL for a specific set number.
- Fixed: OrderMessage.Subject can be Null. Thanks to aalex675 for his contribution.
- New method on IBricklinkClient: GetPartImageForColor. Builds and returns the image URL for a specific part number / color ID.
- New helper method on IBricklinkClient: EnsureImageUrlScheme. Adds (ensures) an URI scheme on image URLs returned by the Bricklink API.
- Coupons
- Nullable annotations
- Renamed UpdatedInventory container to UpdateInventory (breaking)
- Order
- IBricklinkClient implements IDisposable and manages one instance of HttpClient
- Feedback
- Member / Get member rating
- Push Notification
- Setting / Shipping methods
- Renamed IBricklinkClient.GetItemNumber to IBricklinkClient.GetItemNumberAsync (breaking)
- Renamed IBricklinkClient.GetElementId to IBricklinkClient.GetElementIdAsync (breaking)
- User Inventory
- Item Mapping
- OAuth1 handling
- Catalog Item
- Color
- Category
Check out the demo project for full-featured examples.
You need to be registered on bricklink as a seller. Then, use this link to add an access token. Add your client IP address (if applicable) or 0.0.0.0 for both IP address and mask to be able to make API requests from any IP.
Install-Package BricklinkSharp
nuget install BricklinkSharp
BricklinkClientConfiguration.Instance.TokenValue = "<Your Token>";
BricklinkClientConfiguration.Instance.TokenSecret = "<Your Token Secret>";
BricklinkClientConfiguration.Instance.ConsumerKey = "<Your Consumer Key>";
BricklinkClientConfiguration.Instance.ConsumerSecret = "<Your Consumer Secret>";
var client = BricklinkClientFactory.Build();
It's recommended to create and use one IBricklinkClient client throughout the lifetime of your application.
In applications using an IoC container you may register the IBricklinkClient as a service and inject it into consuming instances (e.g. controllers). See the below examples to register the IBricklinkClient as single instance (Singleton).
Autofac example
containerBuilder.Register(c => BricklinkClientFactory.Build())
.As<IBricklinkClient>()
.SingleInstance();
services.AddSingleton(typeof(IBricklinkClient), provider =>
{
return BricklinkClientFactory.Build();
});
var catalogItem = await client.GetItemAsync(ItemType.Part, "6089");
var catalogImage = await client.GetItemImageAsync(ItemType.OriginalBox, "1-12", 0);
var colorId = 34; //Lime.
var uri = client.GetPartImageForColor("43898pb006", 34);
var uri = client.GetMinifigImage("sw1093");
var uri = client.GetSetImage("6090-1");
var uri = client.GetBookImage("5002772");
var uri = client.GetGearImage("BioGMC041");
var uri = client.GetCatalogImage("c58dk2");
var uri = client.GetInstructionImage("1518-1");
var uri = client.GetOriginalBoxImage("2964-1");
var uri = client.EnsureImageUrlScheme("//img.bricklink.com/ItemImage/PN/34/43898pb006.png", "https");
Console.WriteLine(uri.ToString());
//Prints: https://img.bricklink.com/ItemImage/PN/34/43898pb006.png
var supersets = await client.GetSupersetsAsync(ItemType.Minifig, "aqu004", 0);
var subsets = await client.GetSubsetsAsync(ItemType.Set, "1095-1", breakMinifigs: false);
var priceGuide = await client.GetPriceGuideAsync(ItemType.Part, "3003", colorId: 1, priceGuideType: PriceGuideType.Sold, condition: Condition.Used);
var knownColors = await client.GetKnownColorsAsync(ItemType.Part, "3006");
var colors = await client.GetColorListAsync();
var color = await client.GetColorAsync(15);
var categories = await client.GetCategoryListAsync();
var category = await client.GetCategoryAsync(1);
//Include only parts and minifigs.
var includedTypes = new List<ItemType> { ItemType.Part, ItemType.Minifig };
//Exclude all inventories which are unavailable.
var excludedStatusFlags = new List<InventoryStatusType> { Unavailable };
var inventories = await client.GetInventoryListAsync(includedTypes, excludedStatusFlags: excludedStatusFlags);
var newInventory = new NewInventory
{
ColorId = 1,
Condition = Condition.Used,
Item = new ItemBase
{
Number = "3003",
Type = ItemType.Part
},
Quantity = 5,
UnitPrice = 0.01M,
Description = "Good used condition"
};
var inventory = await client.CreateInventoryAsync(newInventory);
var newInventories = new NewInventory[] { //fill with inventories... };
//Note that there will be no response data.
await client.CreateInventoriesAsync(newInventories);
var inventoryList = await client.GetInventoryListAsync();
var id = inventoryList.First().InventoryId;
var updateInventory = new UpdateInventory { ChangedQuantity = 21, Remarks = "Remarks added." };
var inventory = await client.UpdateInventoryAsync(id, updateInventory);
var inventoryList = await client.GetInventoryListAsync();
var id = inventoryList.First().InventoryId;
await client.DeleteInventoryAsync(id);
The method returns an array of ItemMapping objects. If a color ID is specified the array will contain just one element. Otherwise the array will contain mappings for every available color.
var itemMappings = await client.GetElementIdAsync("3003", 1);
var itemMapping = await client.GetItemNumberAsync("300301");
var notifications = await client.GetNotificationsAsync();
var shippingMethods = await client.GetShippingMethodListAsync();
var shippingMethod = await client.GetShippingMethodAsync(123);
var rating = await client.GetMemberRatingAsync("bluser");
var feedbackInList = await client.GetFeedbackListAsync(FeedbackDirection.In);
var feedbackOutList = await client.GetFeedbackListAsync(FeedbackDirection.Out);
var feedbackListAll = await client.GetFeedbackListAsync();
var feedbackListAll = await client.GetFeedbackListAsync()
var id = feedbackListAll.First().FeedbackId;
var feedback = await client.GetFeedbackAsync(id);
var orderId = 1234567; //Must be a valid order ID.
var feedback = await client.PostFeedbackAsync(orderId, RatingType.Praise, "Awesome transaction, praise!");
var feedbackId = 1234567; //Must be a valid feedback ID.
await client.ReplyFeedbackAsync(feedbackId, "Thank you for your kind comment.");
//Exclude all purged orders.
var orders = await client.GetOrdersAsync(OrderDirection.Out, excludedStatusFlags: new List<OrderStatus>
{
OrderStatus.Purged
});
//Only paid orders that must be shipped.
var orders = await client.GetOrdersAsync(OrderDirection.Out, includedStatusFlags: new List<OrderStatus>
{
OrderStatus.Paid
});
var orderId = 123456789; //Must be a valid order ID.
var order = await client.GetOrderAsync(orderId);
var orderId = 1234566789; //Must be a valid order ID.
var itemsBatchList = await client.GetOrderItemsAsync(orderId);
foreach (var itemsBatch in itemsBatchList)
{
foreach (var item in itemsBatch)
{
//Process item...
}
}
var orderId = 123456789; //Must be a valid order ID.
var messages = await client.GetOrderMessagesAsync(orderId);
var orderId = 123456789; //Must be a valid order ID.
var feedbacks = await client.GetOrderFeedbackAsync(orderId);
var orderId = 123456789; //Must be a valid order ID.
//Note: you must only set properties which should be updated. Leave all others Null.
var updateOrder = new UpdateOrder();
updateOrder.Remarks = "Add remark";
updateOrder.IsFiled = true;
updateOrder.Cost.Insurance = 2.5m;
updateOrder.Cost.Etc1 = 1.0m;
updateOrder.Shipping.TrackingNo = "1234567892";
updateOrder.Shipping.TrackingLink = "www.foo.bar/123456789";
await client.UpdateOrder(orderId, updateOrder);
var orderId = 123456789; //Must be a valid order ID.
try
{
//Note that the order must be outgoing in order to be able to set it to 'Shipped'.
await client.UpdateOrderStatusAsync(orderId, OrderStatus.Shipped);
}
catch (Exception exception)
{
//Handle invalid operation.
}
var orderId = 123456789; //Must be a valid order ID.
try
{
//Note that the order must be outgoing in order to be able to set it to 'Received'.
await client.UpdatePaymentStatusAsync(orderId, PaymentStatus.Received);
}
catch (Exception exception)
{
//Handle invalid operation.
}
var orderId = 123456789; //Must be a valid order ID.
try
{
await client.SendDriveThruAsync(orderId, true);
}
catch (Exception exception)
{
//Handle invalid operation.
}
var includesStatusTypes = new List<CouponStatus>
{
CouponStatus.Open
}
var coupons = await client.GetCouponsAsync(Direction.Out, includedCouponStatusTypes: includesStatusTypes);
var couponId = 123456789; //Must be a valid coupon ID.
var coupon = await client.GetCouponAsync(couponId);
var newCoupon = new NewCoupon("bluser", "Special gift for you")
{
DiscountType = DiscountType.Percentage,
DiscountRate = 10
};
newCoupon.AppliesTo.ExceptOnSale = true;
newCoupon.AppliesTo.RestrictionType = CouponRestrictionType.ApplyToSpecifiedItemType;
newCoupon.AppliesTo.ItemType = ItemType.Part; //Only applies to parts.
var coupon = await client.CreateCouponAsync(newCoupon);
var updateCoupon = new UpdateCoupon
{
DiscountType = DiscountType.Percentage,
DiscountRate = 15 //Increase discount rate to 15 percent.
};
var couponId = 123456789; //Must be a valid coupon ID.
var coupon = await client.UpdateCouponAsync(couponId, updateCoupon);
var couponId = 123456789; //Must be a valid coupon ID.
await client.DeleteCouponAsync(couponId);
⚠️ This method makes a call to the public Bricklink page and parses the received HTML. Therefore, no credentials are required.
ℹ️ The method can optionally call the Foreign exchange rates API in order to fetch the Part-Out-Value in your preferred currency. Fetched API calls will be cached in-memory up to 24 hours.
var itemNo = "21322"; //Uses Sequence Number = 1 (21322-1).
//var itemNo = "1610-2"; //Set Sequence Number explicitly.
//You must sign up on https://exchangeratesapi.io/ (free plan) in order to get your API key.
//Note that this setup line can be done one-time during bootstrapping of your application.
ExchangeRatesApiDotIoConfiguration.Instance.ApiKey = "1234567890";
var currencyCode = "EUR"; //Uses the exchange rate service to convert USD to Euro.
//var currencyCode = null; //Skips calling the exchange rate service and only returns USD. In this case, no API key is required.
var result = await client.GetPartOutValueFromPageAsync(itemNo, breakSetsInSet: true, breakMinifigs: true, includeBox:true,
includeExtraParts: true, includeInstructions:true, itemType: PartOutItemType.Set, currencyCode: currencyCode);