tomgould / apple-news-api
Modern PHP client for the Apple News Publisher API with full Apple News Format document support
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
pkg:composer/tomgould/apple-news-api
Requires
- php: ^8.1
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0|^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- guzzlehttp/guzzle: ^7.0
- guzzlehttp/psr7: ^2.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0|^11.0
- saggre/phpdocumentor-markdown: ^1.0
Suggests
- guzzlehttp/guzzle: PSR-18 HTTP client implementation
- symfony/http-client: Alternative PSR-18 HTTP client
README
A modern, PSR-compliant PHP library for the Apple News Publisher API with full Apple News Format (ANF) document support.
Features
- 🚀 Modern PHP 8.1+ with strict types and named arguments
- 🔌 PSR-18 HTTP Client compatible (works with Guzzle, Symfony, etc.)
- 📝 Full Apple News Format support with a fluent, object-oriented document builder
- 🔐 HMAC-SHA256 Authentication handled automatically
- 📦 Zero Framework Dependencies — use with any framework or standalone
- ✅ Thoroughly Tested — 99%+ code coverage
Requirements
- PHP 8.1 or higher
- A PSR-18 HTTP client (e.g., Guzzle)
- Apple News Publisher API credentials
Installation
composer require tomgould/apple-news-api
You also need a PSR-18 HTTP client and PSR-17 factories. Guzzle is recommended:
composer require guzzlehttp/guzzle guzzlehttp/psr7
Quick Start
use TomGould\AppleNews\Client\AppleNewsClient; use TomGould\AppleNews\Document\Article; use TomGould\AppleNews\Document\Components\{Title, Body, Photo}; use TomGould\AppleNews\Document\Metadata; use GuzzleHttp\Client; use GuzzleHttp\Psr7\HttpFactory; // 1. Create the client $factory = new HttpFactory(); $client = AppleNewsClient::create( keyId: 'your-api-key-id', keySecret: 'your-api-secret', httpClient: new Client(), requestFactory: $factory, streamFactory: $factory ); // 2. Build an article $article = Article::create( identifier: 'my-article-123', title: 'Breaking News Story', language: 'en' ); $article ->addComponent(new Title('Breaking News Story')) ->addComponent(Photo::fromUrl('https://example.com/hero.jpg')) ->addComponent(new Body('This is the article content...')); $article->setMetadata( (new Metadata()) ->addAuthor('Jane Doe') ->setExcerpt('A short summary of the article') ); // 3. Publish to Apple News $response = $client->createArticle('your-channel-id', $article); echo "Published! Article ID: " . $response['data']['id'];
Full Implementation Guide
Getting Your API Credentials
- Sign up for Apple News Publisher
- Create a channel for your publication
- Generate API credentials (Key ID and Secret)
Client Initialization
use TomGould\AppleNews\Client\AppleNewsClient; use GuzzleHttp\Client; use GuzzleHttp\Psr7\HttpFactory; $factory = new HttpFactory(); $httpClient = new Client(); $client = AppleNewsClient::create( keyId: 'your-key-id', keySecret: 'your-base64-secret', httpClient: $httpClient, requestFactory: $factory, streamFactory: $factory );
Building Articles
Create the Article
use TomGould\AppleNews\Document\Article; $article = Article::create( identifier: 'my-internal-id-123', title: 'The Future of Web Development', language: 'en', columns: 7, width: 1024 );
Add Metadata
use TomGould\AppleNews\Document\Metadata; $metadata = (new Metadata()) ->addAuthor('Jane Doe') ->setExcerpt('An in-depth look at modern web frameworks.') ->addKeywords(['PHP', 'Web', 'Programming']) ->setDatePublished(new DateTime()); $article->setMetadata($metadata);
Define Reusable Styles
use TomGould\AppleNews\Document\Styles\ComponentTextStyle; $bodyStyle = (new ComponentTextStyle()) ->setFontName('Helvetica') ->setFontSize(18) ->setLineHeight(24) ->setTextColor('#333333'); $article->addComponentTextStyle('defaultBody', $bodyStyle);
Add Components
use TomGould\AppleNews\Document\Components\{Title, Body, Photo, Heading, Divider}; $article ->addComponent(new Title('The Future of Web Development')) ->addComponent(new Divider()) ->addComponent(new Heading('Introduction', level: 2)) ->addComponent( (new Body('This is the <strong>main</strong> paragraph.')) ->setFormat('html') ->setTextStyle('defaultBody') );
Available Components
| Component | Description |
|---|---|
Title |
Article title |
Heading |
Section headings (levels 1-6) |
Body |
Paragraph text |
Photo |
Single image |
Gallery |
Image gallery |
Video |
Native video |
EmbedWebVideo |
YouTube/Vimeo embeds |
Tweet |
Twitter/X embeds |
Instagram |
Instagram embeds |
FacebookPost |
Facebook embeds |
Pullquote |
Highlighted quotes |
Caption |
Image/video captions |
Divider |
Visual separator |
LinkButton |
Call-to-action buttons |
Container |
Group components together |
Working with Assets
Bundle Assets (Local Files)
$article->addComponent(Photo::fromBundle('hero.jpg')); // Provide the file path when publishing $assets = [ 'bundle://hero.jpg' => '/path/to/hero.jpg' ]; $client->createArticle($channelId, $article, null, $assets);
Remote Assets
$article->addComponent( Photo::fromUrl('https://example.com/image.jpg') );
API Operations
Channels
$channel = $client->getChannel($channelId); $quota = $client->getChannelQuota($channelId);
Sections
$sections = $client->listSections($channelId); $section = $client->getSection($sectionId); $client->promoteArticles($sectionId, ['article-id-1', 'article-id-2']);
Articles
// Create $response = $client->createArticle($channelId, $article, $metadata, $assets); // Read $article = $client->getArticle($articleId); // Search $results = $client->searchArticlesInChannel($channelId, ['pageSize' => 20]); // Update (requires revision token) $client->updateArticle($articleId, $revision, $updatedArticle); // Delete $client->deleteArticle($articleId);
Error Handling
use TomGould\AppleNews\Exception\AppleNewsException; use TomGould\AppleNews\Exception\AuthenticationException; try { $client->createArticle($channelId, $article); } catch (AuthenticationException $e) { // Invalid API credentials (401/403) echo "Auth failed: " . $e->getMessage(); } catch (AppleNewsException $e) { // Other API errors echo "Error: " . $e->getMessage(); echo "Code: " . $e->getErrorCode(); // e.g., 'INVALID_DOCUMENT' echo "Field: " . $e->getKeyPath(); // e.g., 'components[0].text' }
Generating Documentation
Generate a local HTML API reference:
# First-time setup mkdir -p tools composer docs:install # Generate docs composer docs
Open docs/api/index.html in your browser.
Or visit the online docs pages: Apple News API PHPDoc Documentation
Testing
# Run tests composer test # Run with coverage report composer test:coverage
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
License
This library is open-sourced software licensed under the MIT license.