Download the PHP package christian-heiko/bka-api without Composer
On this page you can find all versions of the php package christian-heiko/bka-api. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download christian-heiko/bka-api
More information about christian-heiko/bka-api
Files in christian-heiko/bka-api
Package bka-api
Short Description API-Client for Berner Kulturagenda
License MIT
Homepage https://github.com/christian-heiko/bka-api
Informations about the package bka-api
Berner Kulturagenda API Client
This Guzzle based Client interacts with the Event-Related API of Kulturagenda and In-Situ. Use it to read/create/update/delete Events and get other data such as audiences, categories and so on.
API Credentials
You need a login to one of the platforms and API credentials:
- API v2 — what the BKA profile issues today: one long-lived token, generated in the profile.
Use
V2\Client; see API v2. - API v1 — Client ID, Client Secret, Access Token and Refresh Token, from the platform's support. v1 answers a v2 token with a 500.
Support
This is an unofficial package and neither this nor me are related or working for one of the organizations or related companies. Therefore, I can not offer support for api-sided issues but im happy to support issues related to this package.
This is my first open source package; feel free to contribute or give feedback ✌️
Roadmap
A Wordpress Plugin for common Event Plugins could be an option. Please drop me a message if you would like to help develop such a plugin.
Installation
Requires PHP 8.4+ and works with either Guzzle 7 or Guzzle 8.
The official API documentation is published at
admin.bka.ch/api/doc / admin.insitu.live/api/doc
(OpenAPI source at /openapi.yaml).
API v2
BKA runs a second, undocumented API next to v1: API Platform at {host}/api/v2. Tokens generated in
the BKA profile today are v2 tokens — one long-lived JWT, no client id, secret or refresh token — and
v1 answers such a token with a 500. Use ChristianHeiko\Bka\V2\Client for them:
Full example with error handling: examples/events-v2.php.
What is different in v2
| v1 | v2 | |
|---|---|---|
| Auth | OAuth access token (1 h) + refresh token | one JWT from the BKA profile, no refresh |
| Responses | {code, message, data} |
JSON-LD; collections carry member and totalItems |
| Events addressed by | numeric id, updated with PUT |
slug, updated with PATCH (merge patch) |
| Relations | ids | IRIs, built by V2\Iri — places by slug |
| Dates | Y-m-d\TH:i:s\Z |
RFC 3339 with offset: pass local times in their timezone |
| Images | base64 inside the event | uploadImage() first, then reference the id |
| Ticket link | ticketingUrl |
ticketings (V2\Data\Ticketing) |
| Errors | Guzzle ClientException |
ApiException, ValidationException ($violations), NotFoundException; TransportException when no answer came |
Pitfalls the API does not tell you about
- Drafts are invisible to reads.
event()answers null andevents()leaves them out, while an update still finds them. Never choose between update and create on the strength of a lookup:saveEvent()updates when given a slug and creates only when given none. - A 404 on an update does not prove the event is gone. BKA regenerates the slug on rename, so the
stored slug may just be stale.
saveEvent()throwsNotFoundExceptionrather than creating a second copy; look the event up by its id inallEvents()(published events only) and decide. - No answer is not the same as no effect. After a
TransportExceptiona write may have been applied; keep the ids of fresh uploads and clean them up after the next successful save. event_status,publication_status,recurrenceandspecial_rateare not validated by the API — an unknown value is stored.ticketing_designationis validated.opening_timeandpublication_datecannot be cleared throughEvent: they are left out of the payload when unset.- An update of an event that has images fails with "You do not have permission to reassign the
image" unless it replaces them — even when
imagesis left out. Upload the images again for every update (or send none) anddeleteImage()the replaced ones, which are only detached. Deleting an event deletes its current images. - The slug changes on rename. Keep the one in the response.
- Image legends cannot be set: a multipart
labels[legend]part makes the upload fail with a 500, a flatlegendpart is ignored, and images cannot be patched. show_in_print,organizationandticketing_urlare accepted and dropped.events()lists only the account's own published events and ignores v1's filters (keyword,place,limit); page withpageanditemsPerPage.- A label cannot be removed by an update —
nullis rejected as a structural error.
Create Instance (v1)
The sections from here on describe the v1 client.
Direct
Via .env
Access Tokens
The API issues access tokens that are valid for 1 hour, and refresh tokens valid for 6 months.
The client applies the access token to every request and refreshes it automatically — both when it
notices the token has already expired, and when the API answers a request with 401, in which case
the request is replayed once with the new token. You do not need to handle this yourself.
Because a refreshed token is only useful if you keep it, pass onTokenRefresh to be notified:
Without the callback the refreshed token still works for the lifetime of the instance, but is lost once it goes out of scope, so the next process starts by refreshing again.
Events
Full CRUD Example at examples/events.php
Implemented Endpoints
All arguments are optional. events() accepts date_from, date_to, keyword, limit, member,
multi_day, page, place and free; page and limit only apply where the pagination feature
is enabled.
Pagination
List endpoints return only their data. The rest of the envelope stays reachable, which is what
makes limit/page usable:
Both reflect the most recent call.
Errors
Every exception this package throws implements ChristianHeiko\Bka\Exception\BkaException, so you
can catch the lot with one clause, or narrow to the case you care about:
Each class extends the SPL exception it makes sense as (AuthenticationException is a
RuntimeException, InvalidImageException an InvalidArgumentException), so broader
catch (\Exception $e) blocks keep working.
Timeouts
Requests default to a 30 second timeout and a 10 second connect timeout. Override them — along with
proxies, TLS options and anything else Guzzle accepts — via $guzzleOptions; they are forwarded to
the token endpoint too: