-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Feature: Zendesk integration for retrieving user tickets
Summary
Build a new ZendeskTicketService integration that implements the TicketService contract to retrieve tickets for a user from Zendesk using the Search API. User identification must be done by matching email address. Creating tickets is intentionally out of scope for this task.
Contract reference
The integration must implement the TicketService abstract class:
abstract class TicketService {
abstract getTicket(
options: Tickets.Request.GetTicketParams,
authorization?: string,
): Observable<Tickets.Model.Ticket | undefined>;
abstract getTicketList(
options: Tickets.Request.GetTicketListQuery,
authorization?: string,
): Observable<Tickets.Model.Tickets>;
abstract createTicket(
data: Tickets.Request.PostTicketBody,
authorization?: string,
): Observable<Tickets.Model.Ticket>;
}Scope
- Implement
ZendeskTicketServiceconforming toTicketService. - Implement
getTicketListvia Zendesk Support Search API with filtering and pagination. - Implement
getTicketusing the Tickets API primarily (freshest data), with Search API as a fallback, and ensure the ticket belongs to the requesting user (email match). - Map responses to our internal
Tickets.Model.TicketandTickets.Model.Ticketstypes.
Out of scope
createTicket— leave unimplemented with an explicit not-implemented error.
API
getTickets
- Use Search API that supports ticket filtering and pagination.
- Base query for a user’s tickets:
type:ticket requester:<email> - Allow additional filters based on our request options:
- status
- priority
- date ranges
- Pagination: our public query uses
offsetandlimit(see Tickets model).
getTicket
- Prefer Request API (probably preferable, as it only returns public information that is available to the end user) or Tickets API for freshness and performance, then validate the requester matches the user’s email if necessary.
- Retrieve ticket attachments and comments using separate API request, unless there is a way to fetch them together with the ticket details all at once (this would be preferable as it would limit the total number of API requests).
Authentication
- Support API token auth only. Configure via env vars.
- Use
ZENDESK_API_URLas the full base API URL. - Use
ZENDESK_API_TOKENas an already base64-encoded token and send it in the header:Authentication: Base ${ZENDESK_API_TOKEN}.
User identity
- Identify users by email address. The email must be available via
authorizationcontext or request options (document the exact source in the implementation and README). All results must be scoped to that email. - To get current user, use the
getCurrentUsermethod from theusersmodule in yourZendeskTicketService:see user-account module for an example how to useconstructor( private readonly usersService: Users.Service, ) {} ... const user = this.usersService.getCurrentUser();Users.Service.
Error handling and rate limiting
- Map Zendesk HTTP errors to domain errors like 401/403 (auth), 404 (not found) and others.
Configuration
Environment variables (names may be refined during implementation):
ZENDESK_API_URL(full base API URL)ZENDESK_API_TOKEN(base64-encoded, used inAuthentication: Base ${ZENDESK_API_TOKEN})
Data mapping
Zendesk responses must be mapped to our normalized Tickets model defined in tickets.model.ts and documented here: Tickets model and service contract.
Required fields in our model (Ticket) to populate:
id,createdAt,updatedAt,topic,type,status,propertiesfor other fields like subject, description, address or a form of contact (key/value pairs as needed)
Optional fields:
attachments(map filename/url/size/author/date)comments(author/date/content)
Guidance:
- You might need to fetch ticket fields in order to correctly resolve and map fields.
- Use Zendesk ticket
topic→topic; map Zendeskstatusto ourTicketStatusenum; mappriority→type. - Preserve ISO timestamps for
createdAt/updatedAt. - Ensure all returned lists conform to
Pagination.Paginated<Ticket>(total,data). - See the data model details and examples in the docs: Tickets model.
- See how mocked tickets look that are displayed at our demo: https://demo.openselfservice.com/en/cases
Acceptance criteria
ZendeskTicketServiceis implemented in a new package (e.g.,packages/integrations/zendesk).getTicketList(options, authorization?):- Returns only tickets for the email-identified user.
- Supports filters aligned with our model (see docs):
status,type,topic,dateFrom,dateTo,sort(map to Zendesk query as feasible), plus optionalpriorityandtagsif present in request. - Supports pagination via
offset/limit; correctly maps to Zendeskpage/per_pageand back. - Maps data to
Tickets.Model.Ticketscorrectly.
getTicket(options, authorization?):- Returns the ticket if it belongs to the user; otherwise
undefined(or not-found per domain conventions). - Uses Tickets API primarily; falls back to Search API when necessary, with email validation.
- Returns the ticket if it belongs to the user; otherwise
createTicketexplicitly throws a not-implemented error referencing this issue.- README/docs added for configuration, enabling in DI, and examples.
Implementation notes
- Location:
packages/integrations/zendesk/src/modules/tickets/zendesk-ticket.service.ts. - Pagination mapping: input
offset/limit↔ Zendeskpage/per_page. Translatenext_page/previous_pageto newoffset(see Tickets model). - For fetching data from API:
- Prefer an official Zendesk JavaScript SDK/client if available (for stability, auth handling, and API parity).
- If no official SDK, and an OpenAPI/Swagger spec is available, generate a typed client and models (e.g., with
openapi-generator-cli) and use that. - Otherwise, implement calls using NestJS HTTP module. See NestJS docs: HTTP module.
Follow our integration conventions
- Creating a new integration package: see Adding new integrations
- Scaffolding with generators: see Using generators
- How modules are wired and used in the API Harmonization app: see Data flow
- Ensure your package exports
./integrationand registers theticketsservice inConfigas described in the guides above.
Align with the Tickets data model
- Refer to the Tickets model and service contract for supported query parameters and normalized return types. Map
status,type,topic,dateFrom,dateTo, andsortto Zendesk Search API where possible, documenting any limitations.
Documentation
- Add a new docs page under our docs app at
apps/docs/docs/integrations/tickets/zendesk.md. - Follow the structure used by existing integration descriptions (see examples: Strapi CMS, Algolia, Medusa):
- Overview and prerequisites
- Configuration (env vars)
- Usage examples (
getTicket,getTicketList), filters/pagination - Data mapping to the normalized Tickets model (link to Tickets model)
- Limitations and troubleshooting
Test data and environment variables
Switch the app to use the new Zendesk tickets integration following the guide: Switching integrations.
Use the following environment variables to test against our Zendesk instance (provided API token has read-only access to Zendesk):
ZENDESK_API_URL=https://d3v-hycom-20915.zendesk.com
ZENDESK_API_TOKEN=bzJzLWdoQGh5Y29tLnBsL3Rva2VuOjIwU1BZMUFHQnN0SThpd3lhWjQwQTVuUGt1Y09qR0RwZmptVHRhcHk=In this instance, there are several sample tickets prepared for the user jane@example.com. You can sign in using this user to O2S (see credendials) and go to http://localhost:3000/en/cases to view the tickets retrieved from Zendesk.
As an additional requirement, please provide a short feedback on your experiences with working with this framework - how easy or difficult it was to get started (including starting the project, getting around the monorepo or readings our docs) and to make the required changes.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status