Support agents
Most questions families ask the holiday programme team can be answered from the admin: did my child get a place, did you get my payment, why didn't I get an e-mail? This guide shows how to give an AI agent or a helpdesk tool the same answers through the API, safely.
Set up a read-only service account
Create a service account for the agent. The defaults are made for this case: the roles Admin, Teilnehmer:innen and Zahlungen let it look at everything a support case touches, and the access level Nur lesen guarantees it can't change anything, whatever it is asked to do.
On the server
bin/console ferienpass:api:service-account "Support-Agent" --tenant=musterstadt \
--description="Answers families' questions in the helpdesk"
Leave out a role if the agent doesn't need it. Without Zahlungen, for example, it can't see receipts or ledgers (an account still shows its balance).
Have the agent call GET /me when it starts. It confirms "access": "read" and, on installations with several municipalities, tells the agent which one it works for.
Questions and the calls that answer them
Almost every case starts with finding the family. Search looks across accounts, participants, offers and receipts at once; if you know the e-mail address, filter the accounts directly:
curl -H "Authorization: Bearer $FEPLI_TOKEN" \
"https://ferienpass-musterstadt.de/api/accounts?email=familie.mueller@example.org"
Most endpoints accept the account's e-mail address wherever they take an account, so the agent often doesn't need the UUID at all:
| The family asks | Call |
|---|---|
| "Did Lena get a place?" | GET /attendances?account=familie.mueller@example.org&edition=herbstferien-2026: each application's status, offer and participant |
| "Where is the meeting point?" | GET /offers/{uuid}: dates, meetingPoint, bring |
| "Why is she on the waiting list?" | the application's status, sorting (position on the list) and decisionReason; the offer's vacancies |
| "I never got the confirmation." | GET /sent-messages?account=familie.mueller@example.org: subject, sentAt, deliveryStatus, bounced |
| "What does the e-mail say?" | GET /sent-messages/{uuid}: text |
| "How much do I still owe?" | GET /debtors?account=familie.mueller@example.org: due, paid, balance, openAttendances |
| "Did you get my payment?" | GET /receipts?account=familie.mueller@example.org: status, totalAmount, items |
| "Can I still withdraw my consent?" | GET /consents?account=familie.mueller@example.org |
| "What has the team noted?" | GET /accounts/{uuid}/comments and the same for the application |
If an account is blockedEmail, e-mails to its address bounced and fepli
stopped sending. That is the answer to many "I never got an e-mail" cases.
Once the mailbox works again, an admin can unblock the
address.
Give the agent tools, not the whole API
An agent works best with a handful of well-described tools rather than a generic HTTP client. A good starting set:
| Tool | Endpoint |
|---|---|
find_family(query) | GET /search?q=… |
get_account(id_or_email) | GET /accounts?email=… or GET /accounts/{uuid} |
list_applications(account, edition?) | GET /attendances?account=…&edition=… |
get_offer(uuid) | GET /offers/{uuid} |
list_sent_messages(account) | GET /sent-messages?account=… |
get_message(uuid) | GET /sent-messages/{uuid} |
get_balance(account) | GET /debtors?account=… |
list_receipts(account) | GET /receipts?account=… |
list_notes(record_type, uuid) | GET /{accounts,attendances,…}/{uuid}/comments |
Pass the API's detail messages back to the agent when a call fails. They are written to be understood and usually say what to try instead, for example which transitions are possible.
Letting the agent act
Once you trust the agent's answers, you can let it act, for example to withdraw an application when a family cancels, or to leave a note for the team. That needs a service account with the access level Lesen und schreiben and a token created with write access.
Withdraw an application and tell the family
curl -X POST "https://ferienpass-musterstadt.de/api/attendances/0192d0e8-3a4b-7c5d-9e6f-7a8b9c0d1e07/transition" \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"transition": "withdraw", "notify": true}'
Leave a note on the account
curl -X POST "https://ferienpass-musterstadt.de/api/accounts/0191c7b2-4d5e-7f60-8a1b-2c3d4e5f6a05/comments" \
-H "Authorization: Bearer $FEPLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body": "Called the family: Lena is ill and can’t come on Wednesday. Withdrawn, they were told by e-mail."}'
Notes written through the API are internal: only the team sees them, and they show the service account's name as author. That makes them a good way for an agent to hand a case over to a person.
A few rules of thumb:
- Start with notes, not actions. An agent that writes "I would withdraw this application" into a comment lets the team check its judgement before it acts.
- Use two service accounts if only some actions should be automated: a read-only one for answering, a writing one for the few tools that act.
- Decide on
notifydeliberately. Transitions only e-mail the family when you pass"notify": true.
Personal data
The agent sees names, addresses and contact details of families and children. Treat its logs and transcripts as you would treat the admin: keep them within your organisation, and delete them when the case is closed. On multi-tenant installations, people of other municipalities come back masked.