potibm / phluesky
An small PHP library for posting messages to the bluesky social network using the AT Protocol.
Requires
- php: ^8.2
- ext-fileinfo: *
- php-http/discovery: ^1.19
- psr/http-client: ^1.0
- psr/http-client-implementation: *
- psr/http-factory: ^1.0
- psr/http-factory-implementation: *
- psr/http-message: ^2.0
- psr/http-message-implementation: *
- psr/simple-cache: ^3.0
Requires (Dev)
- mikey179/vfsstream: ^1.6
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^11
- psalm/plugin-phpunit: ^0.19.0
- symfony/cache: ^7.0
- symfony/http-client: ^7.0
- symplify/easy-coding-standard: ^13.0.0
- vimeo/psalm: ^6.10
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-09 10:27:27 UTC
README
An small PHP library for Bluesky social using the AT Protocol.
Usage
Install
Installing using composer is suggested
composer require potibm/phluesky
You will need a PSR-7, PSR-17 and PSR-18 client or adapter from this list. For development symfony/http-client and nyholm/psr7 are used.
The HTTP service discovery will do the magic. In most cases no additional steps are required.
Setup and posting a simple message
$api = new \potibm\Bluesky\BlueskyApi('nick.bsky.social', 'abcd-efgh-ijkl-mnop'); $postService = new \potibm\Bluesky\BlueskyPostService($api); $post = \potibm\Bluesky\Feed\Post::create('β¨ example mentioning @atproto.com to share the URL π¨ββ€οΈβπ¨ https://en.wikipedia.org/wiki/CBOR.'); $response = $api->createRecord($post);
Adding mentions and links from post text
$post = \potibm\Bluesky\Feed\Post::create('β¨ example mentioning @atproto.com to share the URL π¨ββ€οΈβπ¨ https://en.wikipedia.org/wiki/CBOR.'); $post = $postService->addFacetsFromMentionsAndLinks($post);
Adding mentions and links and tags from post text
$post = \potibm\Bluesky\Feed\Post::create('β¨ example mentioning @atproto.com to share the URL π¨ββ€οΈβπ¨ https://en.wikipedia.org/wiki/CBOR. and #HashtagFun'); $post = $postService->addFacetsFromMentionsAndLinksAndTags($post);
Adding images
https://atproto.com/blog/create-post#images-embeds
Images are provided through a MediaSource. Use FileMediaSource to read from
disk, or BlobMediaSource to upload binary data already held in memory.
use potibm\Bluesky\Media\FileMediaSource; use potibm\Bluesky\Media\BlobMediaSource; $post = \potibm\Bluesky\Feed\Post::create('example post with image attached'); // from a file path $post = $postService->addImage( $post, new FileMediaSource('image.jpg'), 'alt text' ); // from in-memory binary data $post = $postService->addImage( $post, new BlobMediaSource($imageData, 'image/jpeg'), 'alt text' );
Passing a file path string (e.g.
$postService->addImage($post, 'image.jpg', 'alt text')) is deprecated and will be removed in a future version. UseFileMediaSourceinstead.
Adding website card embeds
https://atproto.com/blog/create-post#website-card-embeds
use potibm\Bluesky\Media\FileMediaSource; $post = \potibm\Bluesky\Feed\Post::create('post which embeds an external URL as a card'); $post = $postService->addWebsiteCard( $post, 'https://example.com', 'Example website', 'Example website description', new FileMediaSource('optionalimage.jpg') );
Reply to a post
https://atproto.com/blog/create-post#replies
$post = \potibm\Bluesky\Feed\Post::create('example of a reply'); $post = $postService->addReply( $post, 'at://did:plc:u5cwb2mwiv2bfq53cjufe6yn/app.bsky.feed.post/3k43tv4rft22g' );
Quote a post
https://atproto.com/blog/create-post#quote-posts
$post = \potibm\Bluesky\Feed\Post::create('example of a quote-post'); $post = $postService->addQuote( $post, 'at://did:plc:u5cwb2mwiv2bfq53cjufe6yn/app.bsky.feed.post/3k44deefqdk2g' );
Reusing sessions
By default a new session is created for every BlueskyApi instance. Bluesky
rate-limits session creation, so for long-running or repeated use you should
reuse sessions. Pass any PSR-16 cache to
the constructor; this example uses symfony/cache:
composer require symfony/cache
use potibm\Bluesky\HttpComponentsManager; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Psr16Cache; $cache = new Psr16Cache(new FilesystemAdapter('phluesky', 0, sys_get_temp_dir())); $api = new \potibm\Bluesky\BlueskyApi( 'nick.bsky.social', 'abcd-efgh-ijkl-mnop', new HttpComponentsManager(), cache: $cache );
The session (including the refresh token) is stored in the cache and reused by later instances. When an access token expires, the library automatically refreshes the session and retries the request once.
Any implementation listed under
psr/simple-cache-implementation
works, so you can use whatever cache backend your project already has.
Handling errors
While performing requests using the API, exceptions may be thrown.
The exceptions are of the base type potibm\Bluesky\Exception\Exception.
The exception message will contain details from the API.
try { $response = $api->createRecord($post); } catch (\potibm\Bluesky\Exception\HttpRequestException $e) { echo 'Error performing request on HTTP level: ' . $e->getMessage(); } catch (\potibm\Bluesky\Exception\AuthenticationErrorException $e) { echo 'Unable to authorize: ' . $e->getMessage(); } catch (\potibm\Bluesky\Exception\HttpStatusCodeException $e) { echo 'Unable to perform request on API level: ' . $e->getMessage(); } catch (\potibm\Bluesky\Exception\InvalidPayloadException $e) { echo 'Received unserializable JSON payload: ' . $e->getMessage(); }
License
The MIT License (MIT). Please see License File for more information.