upload
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Travel Product Manager API
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Synthetic API for a single travel offer workflow.
|
||||
Intended order of operations:
|
||||
1. get recent users,
|
||||
2. get top hotels,
|
||||
3. build hotel preference segments from users and hotels,
|
||||
4. build user-to-hotel assignments from segments,
|
||||
5. send hotel offers by email from assignments.
|
||||
Each endpoint has one specific responsibility.
|
||||
The workflow should be interpreted as a strict data pipeline where the output
|
||||
array of one step becomes the input field of the next step.
|
||||
servers:
|
||||
- url: http://demo-api:8010
|
||||
- url: http://localhost:8010
|
||||
- url: https://api.travel.example.com
|
||||
paths:
|
||||
/users/recent:
|
||||
get:
|
||||
operationId: getRecentUsers
|
||||
tags:
|
||||
- travel-offer-workflow
|
||||
summary: Get recent users for travel campaigns
|
||||
description: |
|
||||
Returns a list of recent users active in the last 7 days.
|
||||
By default this endpoint returns up to 30 users because the limit parameter
|
||||
defaults to 30.
|
||||
Output of this endpoint is the users array that should be passed as the users
|
||||
field to /segments/hotel.
|
||||
This endpoint does not retrieve hotels, create segments, create assignments,
|
||||
or send emails.
|
||||
parameters:
|
||||
- in: query
|
||||
name: last_active_after
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
required: false
|
||||
description: |
|
||||
Optional lower bound for user activity time.
|
||||
Only users active after this timestamp should be returned.
|
||||
If omitted, the endpoint behaves like "last 7 days".
|
||||
- in: query
|
||||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
default: 30
|
||||
required: false
|
||||
description: |
|
||||
Maximum number of users to return.
|
||||
If omitted, the endpoint returns up to 30 users.
|
||||
responses:
|
||||
"200":
|
||||
description: |
|
||||
Successful response containing the users array for the first workflow step.
|
||||
This users array should be passed forward to /segments/hotel.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/RecentUsersResponse"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
users:
|
||||
- id: usr_001
|
||||
email: user001@example.com
|
||||
last_active: "2026-03-13T10:00:00Z"
|
||||
- id: usr_002
|
||||
email: user002@example.com
|
||||
last_active: "2026-03-13T09:55:00Z"
|
||||
- id: usr_003
|
||||
email: user003@example.com
|
||||
last_active: "2026-03-13T09:50:00Z"
|
||||
- id: usr_004
|
||||
email: user004@example.com
|
||||
last_active: "2026-03-13T09:45:00Z"
|
||||
- id: usr_005
|
||||
email: user005@example.com
|
||||
last_active: "2026-03-13T09:40:00Z"
|
||||
- id: usr_006
|
||||
email: user006@example.com
|
||||
last_active: "2026-03-13T09:35:00Z"
|
||||
- id: usr_007
|
||||
email: user007@example.com
|
||||
last_active: "2026-03-13T09:30:00Z"
|
||||
- id: usr_008
|
||||
email: user008@example.com
|
||||
last_active: "2026-03-13T09:25:00Z"
|
||||
- id: usr_009
|
||||
email: user009@example.com
|
||||
last_active: "2026-03-13T09:20:00Z"
|
||||
- id: usr_010
|
||||
email: user010@example.com
|
||||
last_active: "2026-03-13T09:15:00Z"
|
||||
- id: usr_011
|
||||
email: user011@example.com
|
||||
last_active: "2026-03-13T09:10:00Z"
|
||||
- id: usr_012
|
||||
email: user012@example.com
|
||||
last_active: "2026-03-13T09:05:00Z"
|
||||
- id: usr_013
|
||||
email: user013@example.com
|
||||
last_active: "2026-03-13T09:00:00Z"
|
||||
- id: usr_014
|
||||
email: user014@example.com
|
||||
last_active: "2026-03-13T08:55:00Z"
|
||||
- id: usr_015
|
||||
email: user015@example.com
|
||||
last_active: "2026-03-13T08:50:00Z"
|
||||
- id: usr_016
|
||||
email: user016@example.com
|
||||
last_active: "2026-03-13T08:45:00Z"
|
||||
- id: usr_017
|
||||
email: user017@example.com
|
||||
last_active: "2026-03-13T08:40:00Z"
|
||||
- id: usr_018
|
||||
email: user018@example.com
|
||||
last_active: "2026-03-13T08:35:00Z"
|
||||
- id: usr_019
|
||||
email: user019@example.com
|
||||
last_active: "2026-03-13T08:30:00Z"
|
||||
- id: usr_020
|
||||
email: user020@example.com
|
||||
last_active: "2026-03-13T08:25:00Z"
|
||||
- id: usr_021
|
||||
email: user021@example.com
|
||||
last_active: "2026-03-13T08:20:00Z"
|
||||
- id: usr_022
|
||||
email: user022@example.com
|
||||
last_active: "2026-03-13T08:15:00Z"
|
||||
- id: usr_023
|
||||
email: user023@example.com
|
||||
last_active: "2026-03-13T08:10:00Z"
|
||||
- id: usr_024
|
||||
email: user024@example.com
|
||||
last_active: "2026-03-13T08:05:00Z"
|
||||
- id: usr_025
|
||||
email: user025@example.com
|
||||
last_active: "2026-03-13T08:00:00Z"
|
||||
- id: usr_026
|
||||
email: user026@example.com
|
||||
last_active: "2026-03-13T07:55:00Z"
|
||||
- id: usr_027
|
||||
email: user027@example.com
|
||||
last_active: "2026-03-13T07:50:00Z"
|
||||
- id: usr_028
|
||||
email: user028@example.com
|
||||
last_active: "2026-03-13T07:45:00Z"
|
||||
- id: usr_029
|
||||
email: user029@example.com
|
||||
last_active: "2026-03-13T07:40:00Z"
|
||||
- id: usr_030
|
||||
email: user030@example.com
|
||||
last_active: "2026-03-13T07:35:00Z"
|
||||
/hotels/top:
|
||||
get:
|
||||
operationId: getTopHotels
|
||||
tags:
|
||||
- travel-offer-workflow
|
||||
summary: Get top hotels for offers
|
||||
description: |
|
||||
Returns a list of candidate hotels for the offer workflow.
|
||||
By default this endpoint returns up to 5 hotels because the limit parameter
|
||||
defaults to 5.
|
||||
Output of this endpoint is the hotels array that should be passed as the hotels
|
||||
field to /segments/hotel.
|
||||
This endpoint does not retrieve users, create segments, create assignments,
|
||||
or send emails.
|
||||
parameters:
|
||||
- in: query
|
||||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 20
|
||||
default: 5
|
||||
required: false
|
||||
description: |
|
||||
Maximum number of hotels to return.
|
||||
If omitted, the endpoint returns up to 5 hotels.
|
||||
- in: query
|
||||
name: city
|
||||
schema:
|
||||
type: string
|
||||
required: false
|
||||
description: |
|
||||
Optional city filter.
|
||||
If provided, only hotels from this city should be returned.
|
||||
responses:
|
||||
"200":
|
||||
description: |
|
||||
Successful response containing the hotels array for the second workflow step.
|
||||
This hotels array should be passed forward to /segments/hotel.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TopHotelsResponse"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
hotels:
|
||||
- id: hotel_001
|
||||
name: Hotel Aurora
|
||||
city: Berlin
|
||||
- id: hotel_002
|
||||
name: Sea Breeze Resort
|
||||
city: Lisbon
|
||||
- id: hotel_003
|
||||
name: Mountain Vista
|
||||
city: Zurich
|
||||
- id: hotel_004
|
||||
name: City Loft
|
||||
city: Amsterdam
|
||||
- id: hotel_005
|
||||
name: River Palace
|
||||
city: Prague
|
||||
/segments/hotel:
|
||||
post:
|
||||
operationId: segmentUsersByHotelPreferences
|
||||
tags:
|
||||
- travel-offer-workflow
|
||||
summary: Segment recent users by hotel preferences
|
||||
description: |
|
||||
Creates hotel-based user segments from two required inputs in one request:
|
||||
users and hotels.
|
||||
The users field must contain the users array returned by /users/recent.
|
||||
The hotels field must contain the hotels array returned by /hotels/top.
|
||||
A common workflow is: get up to 30 recent users, get top hotels, then send
|
||||
both arrays to this endpoint to distribute users across hotels by preference.
|
||||
Output of this endpoint is the segments array used as the segments field in
|
||||
/assignments/hotels.
|
||||
This endpoint does not send emails.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HotelSegmentsRequest"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
users:
|
||||
- id: usr_001
|
||||
email: user001@example.com
|
||||
last_active: "2026-03-13T10:00:00Z"
|
||||
hotels:
|
||||
- id: hotel_001
|
||||
name: Hotel Aurora
|
||||
city: Berlin
|
||||
responses:
|
||||
"200":
|
||||
description: |
|
||||
Successful response containing the segments array.
|
||||
This segments array should be passed forward to /assignments/hotels.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HotelSegmentsResponse"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
segments:
|
||||
- segment_id: seg_berlin
|
||||
hotel_id: hotel_001
|
||||
user_ids: ["usr_001", "usr_002"]
|
||||
/assignments/hotels:
|
||||
post:
|
||||
operationId: assignUsersToHotels
|
||||
tags:
|
||||
- travel-offer-workflow
|
||||
summary: Assign users to hotels based on segments
|
||||
description: |
|
||||
Builds final user-to-hotel assignments from segments.
|
||||
The segments field must contain the segments array returned by /segments/hotel.
|
||||
Output of this endpoint is the assignments array used as the assignments field
|
||||
in /emails/send-offers.
|
||||
This endpoint does not send emails and does not fetch users or hotels.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AssignmentsRequest"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
segments:
|
||||
- segment_id: seg_berlin
|
||||
hotel_id: hotel_001
|
||||
user_ids: ["usr_001", "usr_002"]
|
||||
responses:
|
||||
"200":
|
||||
description: |
|
||||
Successful response containing the assignments array.
|
||||
This assignments array should be passed forward to /emails/send-offers.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AssignmentsResponse"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
assignments:
|
||||
- user_id: usr_001
|
||||
hotel_id: hotel_001
|
||||
- user_id: usr_002
|
||||
hotel_id: hotel_001
|
||||
/emails/send-offers:
|
||||
post:
|
||||
operationId: sendHotelOffersByEmail
|
||||
tags:
|
||||
- travel-offer-workflow
|
||||
summary: Send hotel offers by email
|
||||
description: |
|
||||
Sends hotel offer emails to users based on final assignments.
|
||||
The assignments field must contain the assignments array returned by
|
||||
/assignments/hotels.
|
||||
This endpoint is the final delivery step of the workflow.
|
||||
It does not build new segments or assignments.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EmailOfferRequest"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
template_id: offer_template_2026
|
||||
assignments:
|
||||
- user_id: usr_001
|
||||
hotel_id: hotel_001
|
||||
- user_id: usr_002
|
||||
hotel_id: hotel_001
|
||||
responses:
|
||||
"200":
|
||||
description: |
|
||||
Successful response containing the result of the email delivery step.
|
||||
This is the final output of the workflow.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EmailOfferResponse"
|
||||
examples:
|
||||
sample:
|
||||
value:
|
||||
sent_count: 2
|
||||
failed_count: 0
|
||||
failed: []
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
description: |
|
||||
A recent user eligible to receive a hotel offer email.
|
||||
User objects are produced by /users/recent and then reused in
|
||||
/segments/hotel.
|
||||
type: object
|
||||
required: [id, email, last_active]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Stable unique user identifier.
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email address used in the final offer delivery step.
|
||||
last_active:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Most recent activity timestamp used to identify recent users.
|
||||
Hotel:
|
||||
description: |
|
||||
A hotel candidate that may be recommended to users.
|
||||
Hotel objects are produced by /hotels/top and then reused in
|
||||
/segments/hotel.
|
||||
type: object
|
||||
required: [id, name, city]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Stable unique hotel identifier.
|
||||
name:
|
||||
type: string
|
||||
description: Human-readable hotel name shown in offers.
|
||||
city:
|
||||
type: string
|
||||
description: City where the hotel is located.
|
||||
Segment:
|
||||
description: |
|
||||
A hotel preference segment that groups users for one hotel.
|
||||
Segment objects are produced by /segments/hotel and then reused in
|
||||
/assignments/hotels.
|
||||
type: object
|
||||
required: [segment_id, hotel_id, user_ids]
|
||||
properties:
|
||||
segment_id:
|
||||
type: string
|
||||
description: Stable unique segment identifier.
|
||||
hotel_id:
|
||||
type: string
|
||||
description: Hotel identifier associated with this segment.
|
||||
user_ids:
|
||||
type: array
|
||||
description: User identifiers that belong to this hotel preference segment.
|
||||
items:
|
||||
type: string
|
||||
Assignment:
|
||||
description: |
|
||||
A final mapping between one user and one hotel offer.
|
||||
Assignment objects are produced by /assignments/hotels and then reused in
|
||||
/emails/send-offers.
|
||||
type: object
|
||||
required: [user_id, hotel_id]
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
description: Identifier of the user who should receive the offer.
|
||||
hotel_id:
|
||||
type: string
|
||||
description: Identifier of the hotel assigned to the user.
|
||||
RecentUsersResponse:
|
||||
description: Response containing the users array produced by /users/recent.
|
||||
type: object
|
||||
required: [users]
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
description: |
|
||||
Recent users that should be copied into the users field of
|
||||
/segments/hotel. With the default limit this array usually contains
|
||||
up to 30 users.
|
||||
items:
|
||||
$ref: "#/components/schemas/User"
|
||||
TopHotelsResponse:
|
||||
description: Response containing the hotels array produced by /hotels/top.
|
||||
type: object
|
||||
required: [hotels]
|
||||
properties:
|
||||
hotels:
|
||||
type: array
|
||||
description: |
|
||||
Candidate hotels that should be copied into the hotels field of
|
||||
/segments/hotel. With the default limit this array usually contains
|
||||
up to 5 hotels.
|
||||
items:
|
||||
$ref: "#/components/schemas/Hotel"
|
||||
HotelSegmentsRequest:
|
||||
description: |
|
||||
Request body for building segments from users and hotels.
|
||||
This request combines the users array from /users/recent and the hotels array
|
||||
from /hotels/top.
|
||||
type: object
|
||||
required: [users, hotels]
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
description: |
|
||||
Users from /users/recent. This is typically the same array of up to 30
|
||||
recent users returned by the first step. These users are being
|
||||
distributed across candidate hotels by preference.
|
||||
items:
|
||||
$ref: "#/components/schemas/User"
|
||||
hotels:
|
||||
type: array
|
||||
description: |
|
||||
Hotels from /hotels/top that should be used as candidate destinations
|
||||
for user distribution.
|
||||
items:
|
||||
$ref: "#/components/schemas/Hotel"
|
||||
HotelSegmentsResponse:
|
||||
description: Response containing the segments array produced by /segments/hotel.
|
||||
type: object
|
||||
required: [segments]
|
||||
properties:
|
||||
segments:
|
||||
type: array
|
||||
description: |
|
||||
Segments that should be copied into the segments field of
|
||||
/assignments/hotels.
|
||||
items:
|
||||
$ref: "#/components/schemas/Segment"
|
||||
AssignmentsRequest:
|
||||
description: |
|
||||
Request body for building assignments from the segments array returned by
|
||||
/segments/hotel.
|
||||
type: object
|
||||
required: [segments]
|
||||
properties:
|
||||
segments:
|
||||
type: array
|
||||
description: |
|
||||
Segments from /segments/hotel that should be converted into final
|
||||
user-to-hotel assignments.
|
||||
items:
|
||||
$ref: "#/components/schemas/Segment"
|
||||
AssignmentsResponse:
|
||||
description: Response containing the assignments array produced by /assignments/hotels.
|
||||
type: object
|
||||
required: [assignments]
|
||||
properties:
|
||||
assignments:
|
||||
type: array
|
||||
description: |
|
||||
Assignments that should be copied into the assignments field of
|
||||
/emails/send-offers.
|
||||
items:
|
||||
$ref: "#/components/schemas/Assignment"
|
||||
EmailOfferRequest:
|
||||
description: |
|
||||
Request body for sending offer emails from the assignments array returned
|
||||
by /assignments/hotels.
|
||||
type: object
|
||||
required: [template_id, assignments]
|
||||
properties:
|
||||
template_id:
|
||||
type: string
|
||||
default: offer_template_2026
|
||||
description: Identifier of the email template to use for every assignment in this request.
|
||||
assignments:
|
||||
type: array
|
||||
description: |
|
||||
Assignments from /assignments/hotels that should be emailed in the
|
||||
final step.
|
||||
items:
|
||||
$ref: "#/components/schemas/Assignment"
|
||||
EmailOfferResponse:
|
||||
description: |
|
||||
Result of the final email delivery step.
|
||||
This response does not contain new users, hotels, segments, or assignments.
|
||||
type: object
|
||||
required: [sent_count, failed_count, failed]
|
||||
properties:
|
||||
sent_count:
|
||||
type: integer
|
||||
description: Number of assignments for which an email was sent successfully.
|
||||
failed_count:
|
||||
type: integer
|
||||
description: Number of assignments for which email delivery failed.
|
||||
failed:
|
||||
type: array
|
||||
description: Failed deliveries with reasons for each affected user.
|
||||
items:
|
||||
type: object
|
||||
required: [user_id, reason]
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
description: Identifier of the user whose email delivery failed.
|
||||
reason:
|
||||
type: string
|
||||
description: Human-readable explanation of why the email could not be sent.
|
||||
Reference in New Issue
Block a user