A modern PHP API client library for BoardGameGeek.com using the XML API2.
Require the package with Composer:
composer require jan-wennrich/bgg-apiQuickstart:
use JanWennrich\BoardGameGeekApi\Client;
$client = Client::autocreate();This creates a Client instance with sane defaults, suitable for most users.
Alternatively you may use the constructor to configure the client to your needs. You may pass:
- a custom PSR-18 HTTP client plus PSR-17 request/stream factories
- a
\JanWennrich\BoardGameGeekApi\RetryConfigto configure retry behavior - a custom User-Agent string
- a
Psr\Log\LoggerInterface
Recently the BoardGameGeek API requires authentication to access it.
You must authenticate via an BoardGameGeek API token (recommended) or a BoardGameGeek username & password.
An API Token can be obtained from BoardGameGeek: https://boardgamegeek.com/using_the_xml_api
$client->setAuthorization($apiToken);Important
Authenticating via username & passwords limits the access to resources of the given username.
So you can access the user's collection or plays for example but no general resources like boardgames.
$client->login($username, $password);The login is stored during runtime, so you have to log in again after the program terminates.
To get a single Thing you can use the following method:
$client->getThing(string $id, bool $stats = false, bool $versions = false): ?ThingTo get multiple Things at once, use the following method:
$client->getThings(array $ids, bool $stats = false, bool $versions = false): Thing[]A single Thing provides the following API:
- Basic info:
getId(),getType(),isType($type)getName(),getDescription()getImage(),getThumbnail()getYearPublished()getMinPlayers(),getMaxPlayers()getPlayingTime(),getMinPlayTime(),getMaxPlayTime()getMinAge()
- Links & related entities:
getBoardgameCategories(),getBoardgameMechanics()getBoardgameDesigners(),getBoardgameArtists(),getBoardgamePublishers()getBoardgameExpansions()getBoardgameVersions()getLinks()(raw link objects)getAlternateNames()getBoardgameBasegame()
- Stats (if
stats=truewhen requesting theThing):getRatingAverage()getWeightAverage()getRank()getLanguageDependenceLevel()
Example: Get the thumbnails of "Ark Nova" (ID 342942) and "Gloomhaven" (ID 174430)
$things = $client->getThings([342942, 174430]);
foreach ($things as $thing) {
echo $thing->getThumbnail() . PHP_EOL;
}To search for something you can use the following method:
$client->search(string $query, bool $exact = false, string $type = Type::BOARDGAME): Search\QueryEach item in the Seach\Query is a Search\Result with:
getId(),getType(),isType($type)getName()getYearPublished()
Example: Search for the board game "Terraforming Mars" and list the names of search results
use JanWennrich\BoardGameGeekApi\Type;
$query = $client->search('Terraforming Mars', exact: true, type: Type::BOARDGAME);
echo count($query) . PHP_EOL;
$first = $query[0];
if ($first) {
echo $first->getName() . PHP_EOL;
}To get hot items you can use this method:
$client->getHotItems(string $type = Type::BOARDGAME): HotItem[]A HotItem provides these getters:
getId()getRank()getName()getYearPublished()getThumbnail()
Example: Get hot items and list their ranks and names
$hot = $client->getHotItems();
foreach ($hot as $item) {
echo $item->getRank() . ': ' . $item->getName() . PHP_EOL;
}To get a use you can use this method:
$client->getUser(string $name): ?UserA User provides the following getters:
getId(),getLogin(),getName()getFirstName(),getLastName()getAvatar(),getCountry()getYearRegistered()
Example: Get the avatar of user "Klabauterjan"
$user = $client->getUser('Klabauterjan');
echo $user->getAvatar();To get a collection, you can use this method:
$client->getCollection(array $parameters): CollectionAll parameters as specified by the BoardGameGeek API are supported: https://boardgamegeek.com/wiki/page/BGG_XML_API2#toc13
Each entry of a Collection is a Collection\Item with these getters:
- object info:
getObjectType(),getObjectId(),getSubtype(),getCollId() - metadata:
getName(),getYearPublished(),getImage(),getThumbnail() - stats:
getNumPlays(),getRatingAverage() - players/time:
getMinPlayers(),getMaxPlayers(),getPlayingTime(),getMinPlayTime(),getMaxPlayTime() - status:
getStatus(): Collection\ItemStatus
A Collection\ItemStatus provides this API:
- flags:
isOwn(),isPrevOwned(),isForTrade(),isWant(),isWantToPlay(),isWantToBuy(),isWishlist(),isPreordered() - wishlist info:
getWishlistPriority() - timestamps:
getLastModified()
Example: Get all boardgames owned by user "Klabauterjan" and list them with their name and publish date
$collection = $client->getCollection([
'username' => 'Klabauterjan',
'owned' => 1,
'stats' => 1
]);
echo $collection->count() . PHP_EOL;
foreach ($collection as $item) {
echo $item->getName() . PHP_EOL;
echo $item->getYearPublished() . PHP_EOL;
}To get plays, you can use this method:
$client->getPlays(array $parameters): Play[]All parameters as specified by the BoardGameGeek API are supported: https://boardgamegeek.com/wiki/page/BGG_XML_API2#toc12
A Play object provides these getters:
- core:
getId(),getDate(),getQuantity(),getLength() - flags:
isIncomplete(),isNoWinStats() - location/comments:
getLocation(),getComments() - item info:
getObjectType(),getObjectId(),getObjectName(),getSubtypes() - players:
getPlayers(): Player[]
A Player object provides these getters:
- identity:
getUsername(),getUserid(),getName() - game info:
getStartPosition(),getColor(),getScore(),getRating() - flags:
isNew(),isWin()
Example: Get plays of user "Klabauterjan" and list their date, name of the game and the names of players
$plays = $client->getPlays(['username' => 'Klabauterjan']);
foreach ($plays as $play) {
echo $play->getDate() . ' - ' . $play->getObjectName() . PHP_EOL;
foreach ($play->getPlayers() as $player) {
echo ' - ' . ($player->getName() ?: $player->getUsername()) . PHP_EOL;
}
}The BoardGameGeek API does not immediately provide results to most requests.
Instead it returns a HTTP 202 response and will return the actual data with a later request.
To simplify this, the client has built-in retry behavior when fetching data:
- Retries up to 3 times
- Waits 5 seconds between attempts by default (configurable)
- Automatically retries when BGG responds with HTTP 202 (queued response)
- Retries on transport errors and 5xx responses
- Does not keep retrying on typical 4xx client errors (e.g. missing authentication)
If all attempts fail, an Exception is thrown.
You can customize retry behavior via RetryConfig:
use JanWennrich\BoardGameGeekApi\Client;
use JanWennrich\BoardGameGeekApi\RetryConfig;
$client = Client::autocreate(
retryConfig: new RetryConfig(
maxAttempts: 5,
initialExponentialRetryDelayInSeconds: 1,
)
);To develop/test this library, do the following:
- Clone the repository
- Install dependencies (
composer install)
Tests can be executed by calling:
composer testTo opt in to live API tests, the following environment variables with credentials have to be set, when running composer test:
BGG_AUTH_TOKENBGG_USERNAMEBGG_PASSWORD
To capture real API responses as XML fixtures, use the fixture recorder command:
BGG_AUTH_TOKEN=... BGG_USERNAME=... BGG_PASSWORD=... php tests/record-fixtures.phpThe recorder writes fixtures into tests/fixtures/<endpoint>/ and requires all three environment variables to be set.
The library uses the following tools to ensure functionality & stability:
- PHPUnit for testing
- PHPStan for static analysis
- PHP CS Fixer to enforce code style
- Rector for automated refactorings
- Composer Dependency Analyser for finding unused or unspecified requirements
- GitHub Actions CI for automatic testing
This library is a fork of castro732/bggxmlapi2 which is a fork of nataniel/bggxmlapi2.
Thanks to the original authors for the foundation.
The XML Schema (.xsd) files in tests/xsd/ were taken from tnaskali/bgg-api.
MIT License
See LICENSE for details.
