pisko999 / cardmarket-php-sdk
Wrap Cardmarket API with PHP
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 4
pkg:composer/pisko999/cardmarket-php-sdk
Requires
- php: ^8.1
- spatie/macroable: ^1.0 || ^2.0
- symfony/http-client: ^5.4 || ^6.0 || ^7.0
- webmozart/assert: ^1.9
Requires (Dev)
- dg/bypass-finals: ^1.2
- friendsofphp/php-cs-fixer: ^3.65
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.5.10 || ^10.0 || ^11.0
- symfony/var-dumper: ^5.4 || ^6.0 || ^7.0
This package is auto-updated.
Last update: 2026-01-26 16:27:46 UTC
README
⚠️ API URL Change (v2.3.0+): Cardmarket has migrated to a new API endpoint. This SDK now uses
apiv2.cardmarket.cominstead ofapi.cardmarket.com. The old URL will be disabled by May 1, 2026. Update to v2.3.0+ to ensure continued functionality.
A comprehensive PHP SDK for the Cardmarket API 2.0, providing easy access to all marketplace features including stock management, order handling, wantslists, and more.
Note: This SDK is a fork of the original mamoot64/cardmarket-php-sdk by Nicolas Perussel, extended with additional features, bug fixes, and comprehensive test coverage.
Table of Contents
- Requirements
- Installation
- Quick Start
- Authentication
- API Resources
- Batch Operations
- Helpers
- Error Handling
- Known API Limitations
- Custom Resources
- Breaking Changes
- Testing
- API Documentation
Requirements
- PHP 8.1 or higher
- Composer
- Cardmarket API credentials (app token, app secret, access token, access secret)
Installation
composer require pisko999/cardmarket-php-sdk
Quick Start
use Pisko\CardMarket\Cardmarket; use Pisko\CardMarket\HttpClient\HttpClientCreator; // Initialize the HTTP client with your credentials $httpCreator = new HttpClientCreator(); $httpCreator->setApplicationToken('your_app_token') ->setApplicationSecret('your_app_secret') ->setAccessToken('your_access_token') ->setAccessSecret('your_access_secret'); // Create the Cardmarket client $cardmarket = new Cardmarket($httpCreator); // Start using the API $games = $cardmarket->games()->getGamesList();
Authentication
The SDK uses OAuth 1.0a authentication. You need four credentials from your Cardmarket developer account:
| Credential | Description |
|---|---|
app_token |
Your application's public token |
app_secret |
Your application's secret key |
access_token |
User-specific access token |
access_secret |
User-specific access secret |
App Types
Cardmarket offers three types of applications:
- Dedicated App - For personal use, managing your own account
- Widget App - Runs within Cardmarket interface (limited API access)
- 3rd Party App - For services provided to other users
Note: Some endpoints are restricted based on app type. See the API documentation for details.
API Resources
Games & Expansions
// Get all available TCG games $games = $cardmarket->games()->getGamesList(); // Get single game details $game = $cardmarket->games()->getGame(1); // 1 = Magic: The Gathering // Get all expansions for a game $expansions = $cardmarket->expansions()->getExpansionsListByGame(1); // Get expansion details $expansion = $cardmarket->expansions()->getExpansion(1525); // Get all cards in an expansion $cards = $cardmarket->expansions()->getCardsListByExpansion(1525);
Game IDs
| ID | Game |
|---|---|
| 1 | Magic: The Gathering |
| 2 | World of Warcraft TCG |
| 3 | Yu-Gi-Oh! |
| 5 | The Spoils |
| 6 | Pokémon |
| 7 | Force of Will |
| 8 | Cardfight!! Vanguard |
| 9 | Final Fantasy TCG |
| 10 | Weiß Schwarz |
| 11 | Dragoborne |
| 12 | My Little Pony |
| 13 | Dragon Ball Super |
| 15 | Star Wars: Destiny |
Products & Articles
// Get product details $product = $cardmarket->products()->getProductDetails(273799); // Find products by name $products = $cardmarket->products()->findProducts('Black Lotus', 0, 100, [ 'idGame' => 1, 'exact' => false ]); // Get product list file (CSV) $productList = $cardmarket->products()->getProductListFile(); // Get price guide $priceGuide = $cardmarket->prices()->getPriceGuideFile(); // Get articles for a product (other users' offers) $articles = $cardmarket->articles()->getArticlesByProduct(100569, [ 'minCondition' => 'NM', 'isFoil' => true, 'idLanguage' => 1 ]); // Get articles by user $articles = $cardmarket->articles()->getArticlesByUser('SellerUsername', [ 'idGame' => 1, 'start' => 0, 'maxResults' => 100 ]);
Stock Management
Reading Stock
// Get your stock (paginated, max 100 per request) $stock = $cardmarket->stock()->getStock(0); // start from 0 // Get single article from stock $article = $cardmarket->stock()->getStockArticle(142158699); // Find articles by name $articles = $cardmarket->stock()->findStockArticles('Pikachu', 6); // 6 = Pokemon // Get articles for specific product $articles = $cardmarket->stock()->getStockArticlesOfProduct(100569); // Get articles currently in other users' carts $inCarts = $cardmarket->stockInShoppingCarts()->getArticlesListInUsersShoppingCarts(); // Export stock as CSV file (deprecated but still functional) $stockFile = $cardmarket->stock()->getStockFile(1, false, 1); // gameId, isSealed, languageId
Adding Articles to Stock
use Pisko\CardMarket\Entities\ArticleEntity; use Pisko\CardMarket\Entities\ArticlesEntity; // Create article entity $article = new ArticleEntity([ 'idProduct' => 100569, 'idLanguage' => 1, 'comments' => 'Near Mint condition', 'count' => 4, 'price' => 2.50, 'condition' => 'NM', 'isFoil' => false, 'isSigned' => false, 'isAltered' => false ]); // Add single article $response = $cardmarket->addArticleStock()->add([$article->getArray()]); // Add multiple articles (batch) $articles = new ArticlesEntity([ ['idProduct' => 100569, 'count' => 2, 'price' => 2.50, 'condition' => 'NM'], ['idProduct' => 100570, 'count' => 1, 'price' => 5.00, 'condition' => 'EX'], ]); $response = $cardmarket->addArticleStock()->add($articles);
Updating Articles
// Update article properties (NOT quantity!) $article = new ArticleEntity([ 'idArticle' => 142158699, 'idLanguage' => 1, 'comments' => 'Updated comment', 'price' => 3.00, 'condition' => 'NM' ]); $response = $cardmarket->updateArticleStock()->add([$article->getArray()]);
Important: The regular PUT /stock endpoint cannot change quantities! Use
changeQuantity()instead.
Changing Quantities
// Increase article quantity $response = $cardmarket->stock()->increaseStock(142158699, 2); // Add 2 to existing count // Decrease article quantity $response = $cardmarket->stock()->decreaseStock(142158699, 1); // Remove 1 from count
Deleting Articles
$article = new ArticleEntity([ 'idArticle' => 142158699, 'count' => 1 // Remove 1 from stock ]); $response = $cardmarket->deleteArticleStock()->add([$article->getArray()]);
Stock Export (Async)
// Request stock export $export = $cardmarket->stockExport()->askStockExport(); // Check export status $status = $cardmarket->stockExport()->getStockExportStatus(); // Get specific export $exportDetails = $cardmarket->stockExport()->getStockExport($exportId);
Order Management
// Get received orders (as seller) $orders = $cardmarket->orders()->getReceivedOrders(); // Get sent orders (as buyer) $orders = $cardmarket->orders()->getSentOrders(); // Filter orders by state $orders = $cardmarket->orders()->getOrdersByActorAndState('seller', 'paid'); // States: bought, paid, sent, received, lost, cancelled, evaluated // Get specific order $order = $cardmarket->orders()->getOrder(123456); // Change order state use Pisko\CardMarket\Entities\OrderChangeStateEntity; $cardmarket->orders()->changeOrderState( 123456, // Order ID OrderChangeStateEntity::STATE_CHANGE_SEND // Mark as sent ); // Add tracking number $cardmarket->orders()->setOrderTrackingNumber(123456, '1Z999AA10123456784'); // Evaluate order use Pisko\CardMarket\Entities\EvaluationEntity; $cardmarket->orders()->evaluateOrder( 123456, // Order ID EvaluationEntity::GRADE_VERY_GOOD, // Overall grade EvaluationEntity::GRADE_VERY_GOOD, // Item description accuracy EvaluationEntity::GRADE_VERY_GOOD, // Packaging quality 'Great seller, fast shipping!', // Comment [] // Complaints (empty array) );
Order States
| State | Description |
|---|---|
bought |
Order placed, awaiting payment |
paid |
Payment received |
sent |
Shipped by seller |
received |
Received by buyer |
lost |
Package lost |
cancelled |
Order cancelled |
evaluated |
Order completed and evaluated |
Evaluation Grades
| Grade | Constant | Meaning |
|---|---|---|
| 1 | GRADE_VERY_GOOD |
Very Good |
| 2 | GRADE_GOOD |
Good |
| 3 | GRADE_NEUTRAL |
Neutral |
| 4 | GRADE_BAD |
Bad |
| 10 | GRADE_NA |
Not Applicable |
Wantslists
// Get all wantslists $wantslists = $cardmarket->wantslist()->getWantsLists(); // Get wantslist with items $wantslist = $cardmarket->wantslist()->getWantsList(211682); // Create new wantslist $newList = $cardmarket->wantslist()->createWantsList('EDH Staples', 1); // 1 = MTG // Rename wantslist $cardmarket->wantslist()->renameWantsList(211682, 'Updated Name'); // Delete wantslist $cardmarket->wantslist()->deleteWantsList(211682);
Managing Wantslist Items
use Pisko\CardMarket\Entities\WantslistItemEntity; use Pisko\CardMarket\Entities\WantslistItemsEntity; // Add items $item = new WantslistItemEntity([ 'idProduct' => 100569, 'count' => 4, 'wishPrice' => 10, 'idLanguage' => 1, 'minCondition' => 'NM', 'isFoil' => true ]); $items = new WantslistItemsEntity([$item]); $cardmarket->wantslist()->addItemsToWantsList(211682, $items); // Edit items (requires idWant from existing item) $item = new WantslistItemEntity([ 'idWant' => 12345, 'count' => 2, 'wishPrice' => 15 ]); $items = new WantslistItemsEntity([$item]); $cardmarket->wantslist()->editItemsInWantsList(211682, $items); // Delete items $item = new WantslistItemEntity([ 'idWant' => 12345, 'count' => 1 ]); $items = new WantslistItemsEntity([$item]); $cardmarket->wantslist()->deleteItemsFromWantsList(211682, $items);
Shopping Cart
// Get current cart $cart = $cardmarket->cart()->getCart(); // Add articles to cart (simple method) $cardmarket->cart()->addToCart([ ['idArticle' => 123456, 'amount' => 1], ['idArticle' => 123457, 'amount' => 2] ]); // Remove articles from cart (simple method) $cardmarket->cart()->removeFromCart([ ['idArticle' => 123456, 'amount' => 1] ]); // Empty entire cart $cardmarket->cart()->emptyCart(); // Checkout $cardmarket->cart()->checkout(); // Change shipping address use Pisko\CardMarket\Entities\CartAddressEntity; $address = new CartAddressEntity( 'John Doe', // name '', // extra (optional) '123 Main Street', // street '12345', // zip 'Prague', // city 'CZ' // country code ); $cardmarket->cart()->setCartAddress($address); // Change shipping method (idReservation from cart response) $cardmarket->cart()->setShippingMethod($idReservation, 2); // 2 = shipping method ID
Account Management
// Get current account info $account = $cardmarket->account()->getAccount(); // Get specific user $user = $cardmarket->users()->getUser('Username'); // Find users $users = $cardmarket->users()->findUsers('searchterm'); // Messages $threads = $cardmarket->messages()->getMessagesThread(); $thread = $cardmarket->messages()->getMessagesThreadByUser(123); // 123 = idOtherUser // Send message use Pisko\CardMarket\Entities\MessageEntity; $message = new MessageEntity('Hello, I have a question about my order.'); $cardmarket->messages()->sendMessage(123, $message); // 123 = idOtherUser // Coupons $cardmarket->coupon()->redeemCoupons('COUPON-CODE'); // Or redeem multiple coupons $cardmarket->coupon()->redeemCoupons(['COUPON-1', 'COUPON-2']);
Batch Operations
For operations that modify multiple items (add/update/delete stock), the SDK uses automatic batching:
// Async mode - accumulates items, sends when reaching 100 $cardmarket->addArticleStock()->add($articles, true); // async = true $cardmarket->addArticleStock()->add($moreArticles, true); // Force send accumulated items $response = $cardmarket->addArticleStock()->send(); // Sync mode (default) - sends immediately $response = $cardmarket->addArticleStock()->add($articles); // async = false (default)
Helpers
CsvStockFileHelper
use Pisko\CardMarket\Helpers\CsvStockFileHelper; $stockFile = $cardmarket->stock()->getStockFile(1); $helper = new CsvStockFileHelper($stockFile['stock']); // Save to disk $helper->storeStockFileOnDisk('./my-stock.csv');
GamesHelper
use Pisko\CardMarket\Helpers\GamesHelper; // Check if game ID is valid if (GamesHelper::isGame(1)) { echo "Valid game!"; } // Use constants $mtgId = GamesHelper::MTG; // 1 $pokemonId = GamesHelper::PCG; // 6
UserTypeHelper
use Pisko\CardMarket\Helpers\UserTypeHelper; // User type constants UserTypeHelper::PRIVATE_USER; // 'private' UserTypeHelper::COMMERCIAL_USER; // 'commercial' UserTypeHelper::POWERSELLER; // 'powerseller'
Parameter Types
When passing search parameters to API methods, use the correct PHP types:
Boolean Parameters
Use PHP booleans (true/false), not strings. The SDK automatically converts them to the API format.
// ✅ Correct - use PHP booleans $articles = $cardmarket->articles()->getArticles($productId, 0, 100, [ 'isFoil' => true, 'isSigned' => false, 'isAltered' => false, ]); // ❌ Wrong - don't use strings $articles = $cardmarket->articles()->getArticles($productId, 0, 100, [ 'isFoil' => 'true', // Wrong! 'isSigned' => 'false', // Wrong! ]);
Integer Parameters
Use PHP integers for IDs and numeric values:
$products = $cardmarket->products()->findProducts('Black Lotus', 0, 100, [ 'idGame' => 1, // Integer 'idLanguage' => 1, // Integer 'exact' => true, // Boolean ]);
String Parameters
Use strings for conditions, comments, and text fields:
$articles = $cardmarket->articles()->getArticles($productId, 0, 100, [ 'minCondition' => 'NM', // String: MT, NM, EX, GD, LP, PL, PO ]);
Condition Values
| Value | Meaning |
|---|---|
MT |
Mint |
NM |
Near Mint |
EX |
Excellent |
GD |
Good |
LP |
Light Played |
PL |
Played |
PO |
Poor |
Error Handling
use Pisko\CardMarket\Exception\HttpClientException; use Pisko\CardMarket\Exception\HttpServerException; use Pisko\CardMarket\Exception\HttpClientNotConfiguredException; use Pisko\CardMarket\Exception\NonExistsResourceException; use Pisko\CardMarket\Exception\UnknownErrorException; try { $product = $cardmarket->products()->getProductDetails(999999999); } catch (HttpClientException $e) { // 4xx errors (bad request, unauthorized, not found, etc.) echo "Client error: " . $e->getMessage(); echo "Status code: " . $e->getCode(); } catch (HttpServerException $e) { // 5xx errors (server errors) echo "Server error: " . $e->getMessage(); } catch (HttpClientNotConfiguredException $e) { // Missing credentials echo "Configuration error: " . $e->getMessage(); }
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | OK - Request successful |
| 206 | Partial Content - Paginated response, more data available |
| 204 | No Content - Request successful, no more data |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid credentials |
| 403 | Forbidden - Access denied |
| 404 | Not Found - Resource doesn't exist |
| 500+ | Server Error - Cardmarket server issue |
Known API Limitations
The following are known issues or limitations in the Cardmarket API itself (not SDK bugs):
Messages API
| Method | Issue |
|---|---|
findMessages() |
Endpoint broken - Returns HTTP 400 "This feature is currently unavailable" but marks all unread messages as read anyway! Do not use. |
deleteMessagesByUser() |
Does not delete messages - API returns 200 OK but messages remain. Use deleteOneMessageByUser() to delete individual messages instead. |
Wantslists API
| Method | Issue |
|---|---|
createWantslist() |
Name length limit - Wantslist names are limited to approximately 8 characters. Longer names may be truncated or rejected. |
Custom Resources
Extend the SDK with your own resources:
namespace App\CardmarketResources; use Pisko\CardMarket\Resources\HttpCaller; class MyCustomResource extends HttpCaller { public function getExpensiveCards(int $gameId): array { $products = $this->get('/products/find?idGame=' . $gameId . '&minPrice=100'); // Custom logic here return $products; } }
Register and use:
$cardmarket->registerResources('custom', MyCustomResource::class); $expensiveCards = $cardmarket->custom()->getExpensiveCards(1);
Note: You cannot override default resource names.
Breaking Changes
Version 2.0.0 (January 2026)
Removed Features
-
isPlaysetproperty removed- As of November 11, 2024, Cardmarket no longer supports playsets
- Removed from:
ArticleEntity,WantslistItemEntity,ArticlesResource - Migration: Remove any
isPlaysetparameters from your code
-
Captcha endpoint removed
- The
/captchaendpoint was deprecated in Cardmarket API 2.0 - Removed:
CaptchaResourceclass andcaptcha()method - Migration: Remove any captcha-related code
- The
Method Renames
StockExport()→stockExport()(camelCase consistency)
Fixed Bugs
- Fixed wrong endpoint in
getStockArticlesOfProduct()(/stock/%d→/stock/products/%d) - Fixed switch case bug in HTTP error handling
- Fixed
hasError()return type (int→bool) - Added XML escaping to all entity XML outputs for security
- Added proper null handling for API response headers
Testing
# Clone repository git clone git@github.com:pisko999/cardmarket-php-sdk.git cd cardmarket-php-sdk # Install dependencies composer install # Run tests composer test # Run static analysis composer stan # Check coding standards composer cs-check # Fix coding standards composer cs-fix # Run all checks (cs-check, stan, test) composer check # Run tests with coverage composer test-coverage-html
API Documentation
Complete API documentation is available in the docs/ folder:
- API Overview
- Authentication
- Stock Management
- Order Management
- Wantslist Management
- Response Codes
- Entities
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Credits
- Original SDK: mamoot64/cardmarket-php-sdk by Nicolas Perussel
- Current maintainer: Petr Spinar