From d70d719a08ef23723778611531869673b72cc3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 13:46:13 +1000 Subject: [PATCH 01/32] feat: update to openapi 3.1 and fix errors About 140 errors fixed, a few to go. --- .github/workflows/check-specs.yml | 37 - .github/workflows/lint-vacuum.yml | 24 + topsort-api-v2.yml | 1245 +++++++++++++++-------------- 3 files changed, 659 insertions(+), 647 deletions(-) delete mode 100644 .github/workflows/check-specs.yml create mode 100644 .github/workflows/lint-vacuum.yml diff --git a/.github/workflows/check-specs.yml b/.github/workflows/check-specs.yml deleted file mode 100644 index 002f11e..0000000 --- a/.github/workflows/check-specs.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: check-specs -on: - pull_request: - branches: - - main -jobs: - check-specs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - - name: Cache node modules - id: cache-node - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('.github/workflows/check-specs.yml') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install Dependencies - run: npm install -g prettier@2.5.1 @openapitools/openapi-generator-cli@2.4.24 - - - name: Check Formatting - run: prettier --check . - - - name: Check Spec (Topsort Endpoints v1) - run: openapi-generator-cli validate -i topsort-api-v1.yml - - - name: Check Spec (Topsort Endpoints v2) - run: openapi-generator-cli validate -i topsort-api-v2.yml - - - name: Check Spec (Catalog CRUD API) - run: openapi-generator-cli validate -i catalog-crud-api.yml - - - name: Check Spec (Catalog Service) - run: openapi-generator-cli validate -i topsort-catalog-service.yml diff --git a/.github/workflows/lint-vacuum.yml b/.github/workflows/lint-vacuum.yml new file mode 100644 index 0000000..9efea41 --- /dev/null +++ b/.github/workflows/lint-vacuum.yml @@ -0,0 +1,24 @@ +name: "Lint OpenAPI spec with vacuum" + +on: + pull_request: + +permissions: + contents: read + pull-requests: write + +jobs: + vacuum-lint: + name: Run OpenAPI linting with vacuum + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check Formatting + run: npx prettier --check topsort-api-v2.yml + + - name: Run OpenAPI lint with vacuum + uses: pb33f/vacuum-action@v2 + with: + openapi_path: "topsort-api-v2.yml" + github_token: ${{ secrets.GITHUB_TOKEN } diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index ee97b5c..7ece3d1 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -1,9 +1,12 @@ -openapi: 3.0.1 +openapi: 3.1.0 info: title: Topsort Endpoints v2 API Reference - description: >- - In order for a storefront to be able to run auctions in Topsort and report auction-related events back to Topsort, + description: > + In order for a storefront to be able to run auctions in Topsort and + report auction-related events back to Topsort, + both the `/v2/auctions` and `/v2/events` endpoints must be integrated. + Below are the endpoint and model definitions for each. contact: email: wicha@topsort.com @@ -15,114 +18,43 @@ info: backgroundColor: '#fff' altText: Topsort version: 2.0.0 - servers: - url: https://api.topsort.com description: Base API URL - tags: - name: Auctions - description: An auction determines which products should be promoted based on the vendors' bids. + description: + An auction determines which products should be promoted based on + the vendors' bids. - name: Events - description: | - **The specification details, particularly around placement data, may change in the short term.** + description: > + **The specification details, particularly around placement data, + may change in the short term.** + **If this is not acceptable for your integration, please use [Events V1](https://docs.topsort.com/reference/reportevent) as an alternative.** Significant consumer interactions on the marketplace app. - name: Toptimize - description: | - An out-of-the-box solution for prediction, ranking, retrieval, and other elements of ad selection. - - name: Models - x-displayName: All Models - description: | - ## AssetSource - - - ## Auction (Banners) - - - ## Auction (Sponsored Listings) - - - ## Auction Result (Banners) - - - ## Auction Result (Sponsored Listings) - - - ## Category - - - ## Category Disjunction - - - ## Click - - - ## Error - - - ## Events Request - - - ## Geotargeting - - - ## Impression - - - ## Products - - - ## Purchase - - - ## Purchase Item - - - ## Winner (Banners) - - - ## Winner (Sponsored Listings) - - - ## Page - - - ## RankingRequest - - - ## PredictionRequest - - - ## RankingResult - - - ## PredictionResult - - - ## RankingWinner - - - ## Interaction Object - - + description: > + An out-of-the-box solution for prediction, ranking, retrieval, and + other elements of ad selection. security: - - BearerAuth: [] - + - HTTPBearer: [] paths: /v2/auctions: post: tags: - Auctions summary: Create auctions - description: | - Use the `/auctions` endpoint to create auctions. Each batch of auction requests can be a combination of - sponsored listing auctions and banner auctions. Each auction type has a unique body schemas. + description: > + Use the `/auctions` endpoint to create auctions. Each batch of + auction requests can be a combination of sponsored listing auctions + and banner auctions. Each auction type has a unique body schemas. operationId: createAuctions requestBody: - description: | + description: > The information describing what will be auctioned. + Topsort will run an auction for each batched auction request, for which products' bids will compete against each other. content: application/json: @@ -135,43 +67,17 @@ paths: $ref: '#/components/schemas/AuctionRequest' minItems: 1 maxItems: 5 - required: - - auctions - example: - auctions: - - type: listings - slots: 1 - category: - disjunctions: - - - c_large - - c_medium - - type: listings - slots: 2 - products: - ids: - - p_PJbnN - - p_ojng4 - - p_8VKDt - - p_Mfk15 - geoTargeting: - location: New York - - type: banners - slots: 1 - slotId: categories-ribbon-banner - category: - id: c_yogurt - - type: banners - slots: 1 - slotId: homepage-banner required: true responses: - 201: + '201': description: > - The auction results. - The list of winners will contain at most `slots` entries per auction. - It may contain fewer or no entries at all if there aren't enough products with usable bids, that is, - a bid amount greater than the reserve price and belonging to a campaign with enough remaining budget. - Bids become unusable if campaign budget is exhausted, the bid is disqualified to preserve spend pacing, etc. + The auction results. The list of winners will contain at most + `slots` entries per auction. It may contain fewer or no entries at + all if there aren't enough products with usable bids, that is, a bid + amount greater than the reserve price and belonging to a campaign + with enough remaining budget. Bids become unusable if campaign + budget is exhausted, the bid is disqualified to preserve spend + pacing, etc. content: application/json: schema: @@ -185,8 +91,8 @@ paths: maxItems: 5 required: - results - example: - results: + examples: + - results: - winners: - rank: 1 type: product @@ -194,6 +100,7 @@ paths: resolvedBidId: WyJiX01mazExIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTMyNjYtY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0== campaignId: 82588593-85c5-47c0-b125-07e315b7f2b3 error: false + - results: - winners: - rank: 1 type: product @@ -215,11 +122,12 @@ paths: asset: - url: https://topsort.cdnprovider.com/lhs-banner-image-for-p_PJbnN-1x.png error: false + - results: - winners: [] error: false - 400: + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' /v2/auctions/sponsored-brand: post: @@ -228,8 +136,9 @@ paths: summary: Create sponsored brand auctions operationId: createSponsoredBrandAuctions requestBody: - description: | + description: > The information describing what will be auctioned. + Topsort will run an auction for each batched auction request, for which products bids will compete against each other. content: application/json: @@ -246,13 +155,15 @@ paths: - auctions required: true responses: - 201: + '201': description: > - The auction results. - The list of winners will contain at most `winners` entries per auction. - It may contain fewer or no entries at all if there aren't enough products with usable bids, that is, - a bid amount greater than the reserve price and belonging to a campaign with enough remaining budget. - Bids become unusable if campaign budget is exhausted, the bid is disqualified to preserve spend pacing, etc. + The auction results. The list of winners will contain at most + `winners` entries per auction. It may contain fewer or no entries at + all if there aren't enough products with usable bids, that is, a bid + amount greater than the reserve price and belonging to a campaign + with enough remaining budget. Bids become unusable if campaign + budget is exhausted, the bid is disqualified to preserve spend + pacing, etc. content: application/json: schema: @@ -266,9 +177,9 @@ paths: maxItems: 5 required: - results - 400: + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' /v2/auctions/travel: post: @@ -276,14 +187,18 @@ paths: - Auctions summary: Create travel auctions description: - Use the `/auctions/travel` endpoint to create batch auctions for sponsored travel listings. We support - two types of sponsored travel listings, hotels and flights. Each batch of auction requests can be a combination - of sponsored hotel and flight listing auctions. Each auction type has a unique body schemas. + Use the `/auctions/travel` endpoint to create batch auctions for + sponsored travel listings. We support two types of sponsored travel + listings, hotels and flights. Each batch of auction requests can be a + combination of sponsored hotel and flight listing auctions. Each auction + type has a unique body schemas. operationId: createTravelAuctions requestBody: - description: | + description: > The information describing what will be auctioned. + Topsort will run an auction for each batched auction request, for which travel products' bids will compete + against each other. content: application/json: @@ -298,46 +213,48 @@ paths: maxItems: 5 required: - auctions - example: - auctions: - - type: hotels - slots: 2 - products: - - id: hotel-1 - qualityScore: 0.7 - - id: hotel-2 - category: - id: hotel-boutique - travelContext: - travelStartDate: 2025-01-01 - travelEndDate: 2025-01-15 - site: argentina - passengers: 2 - travelerType: couple - - type: flights - slots: 2 - products: - - id: 'L0_SAO-ORL' - variationID: '001' - price: 1500 - qualityScore: 0.7 - - id: 'L0_SAO-ORL' - variationID: '002' - price: 2000 - travelContext: - site: argentina - passengers: 2 - route: SAO-ORL - flightType: one-way + examples: + - auctions: + - type: hotels + slots: 2 + products: + - id: hotel-1 + qualityScore: 0.7 + - id: hotel-2 + category: + id: hotel-boutique + travelContext: + travelStartDate: 2025-01-01 + travelEndDate: 2025-01-15 + site: argentina + passengers: 2 + travelerType: couple + - type: flights + slots: 2 + products: + - id: L0_SAO-ORL + variationID: '001' + price: 1500 + qualityScore: 0.7 + - id: L0_SAO-ORL + variationID: '002' + price: 2000 + travelContext: + site: argentina + passengers: 2 + route: SAO-ORL + flightType: one-way required: true responses: - 201: + '201': description: > - The auction results. - The list of winners will contain at most `winners` entries per auction. - It may contain fewer or no entries at all if there aren't enough products with usable bids, that is, - a bid amount greater than the reserve price and belonging to a campaign with enough remaining budget. - Bids become unusable if campaign budget is exhausted, the bid is disqualified to preserve spend pacing, etc. + The auction results. The list of winners will contain at most + `winners` entries per auction. It may contain fewer or no entries at + all if there aren't enough products with usable bids, that is, a bid + amount greater than the reserve price and belonging to a campaign + with enough remaining budget. Bids become unusable if campaign + budget is exhausted, the bid is disqualified to preserve spend + pacing, etc. content: application/json: schema: @@ -351,7 +268,7 @@ paths: maxItems: 5 required: - results - example: + examples: - results: - resultType: hotels winners: @@ -375,30 +292,40 @@ paths: resolvedBidId: ChAGg-P56Wu4MRUEHdX8VEfLHkBEk4_aEXz9fb-YZtxjwN3IJkBEk5Ms_W2_c8Yx_vZJhzSXKlVLDUJQDUJssl8 campaignId: cb8ed0a7-0ecf-4ffb-a863-022f862649ec variationID: '001' - 400: + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' /v2/events: post: tags: - Events summary: Report events - description: | - Use the `/events` endpoint to report user interactions and activity in on a marketplace: + description: > + Use the `/events` endpoint to report user interactions and activity + in on a marketplace: + - **Impressions** — a user viewed an asset. + - **Clicks** — a user clicked on an asset. + - **Purchases** — a user created an order. + - **Pageviews** — a user visited a page. + Interactions require either a `resolvedBidId`, for sponsored events coming from the `/v2/auctions` response, + or an `entity` that describes the entity that was interacted with, in the case of organic or non-sponsored events. + For analytics purposes, you can use the `placement` field to differentiate different listings or banners. + For example, on a product page with a carousel of products, you can track impressions and clicks related to the carousel + by including `/carousel` at the end of the `path` field in the `placement` object. This allows you to monitor - the performance of carousel products in the [Data Room](https://docs.topsort.com/knowledge-base/analytics/data-room/). + the performance of carousel products in the [Data Room](https://docs.topsort.com/knowledge-base/analytics/data-room/). operationId: reportEvents requestBody: content: @@ -407,24 +334,29 @@ paths: $ref: '#/components/schemas/EventsRequest' required: true responses: - 204: + '204': description: All events were reported successfully. - 401: - $ref: '#/components/responses/UnauthorizedError' - 400: + '400': $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/UnauthorizedError' /v2/events/beta/link-users: post: tags: - Events summary: '[Beta] Report Link Users' - description: | - Use the `/events/beta/link-users` endpoint to report to Topsort linked opaque user IDs. + description: > + Use the `/events/beta/link-users` endpoint to report to Topsort + linked opaque user IDs. + This endpoint allows linking two opaque user IDs for attribution purposes. The `from` field represents the + original opaque user ID, and the `to` field represents the target opaque user ID to be linked. The request + will fail if the `from` and `to` opaque user IDs are the same. + Contact your sales representative to gain access to this endpoint and start using it. x-beta: 'true' operationId: linkUsers @@ -447,34 +379,37 @@ paths: required: - from - to - example: - from: 'user123' - to: 'user456' + examples: + - from: user123 + to: user456 required: true responses: - 204: + '204': description: Users account link was reported successfully. - 401: - $ref: '#/components/responses/UnauthorizedError' - 400: + '400': $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/UnauthorizedError' /toptimize/v1/rank: post: tags: - Toptimize summary: '[Beta] Rank objects' operationId: createRanking - description: | + description: > > ⚠️ **Beta Access Required** + > Contact your sales representative to gain access to this endpoint and start using it. + Use the `/ranking` endpoint to re-rank objects to show on a page. This endpoint can retrieve sponsored + and non-sonsored objects and rank them together, according to an appropriate context and behavior information. requestBody: - description: | - The context information to get the ranking, to rank organic and sponsored products. - + description: > + The context information to get the ranking, to rank organic and + sponsored products. x-beta: 'true' content: application/json: @@ -489,22 +424,26 @@ paths: maxItems: 5 required: - ranking - example: - ranking: + examples: + - ranking: - type: listings slots: 3 pageSize: 3 category: - ids: ['sneakers', 'shoes'] + ids: + - sneakers + - shoes products: - ids: ['p_PJbnN', 'p_ojng4'] + ids: + - p_PJbnN + - p_ojng4 required: true responses: - 201: + '201': description: > - The ranking results. - The list of winners will contain at most `slots` entries per auction. - It may contain fewer or no entries at all if there aren't enough products to fill the slots. + The ranking results. The list of winners will contain at most + `slots` entries per auction. It may contain fewer or no entries at + all if there aren't enough products to fill the slots. content: application/json: schema: @@ -518,8 +457,8 @@ paths: maxItems: 5 required: - results - example: - results: + examples: + - results: - products: - rank: 1 type: organic @@ -534,119 +473,136 @@ paths: id: p_PJbnN resolvedItemId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= error: false - 400: + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' - /toptimize/v1/predictions: post: tags: - Toptimize summary: '[Beta] Add Quality Score' - description: | - Use the `/predictions` endpoint to get contextual predictions of conversion and relevance metrics, + description: > + Use the `/predictions` endpoint to get contextual predictions of + conversion and relevance metrics, + which are personalized by user and context. + In order to provide predictions, Topsort requires that events are also sent, as a source of + information. operationId: getPredictions requestBody: - description: | + description: > > ⚠️ **Beta Access Required** + > Contact your sales representative to gain access to this endpoint and start using it. + The context information for the predictions, including which metrics to predict. x-beta: 'true' content: application/json: schema: $ref: '#/components/schemas/PredictionRequest' - example: - metrics: - ctr: true - opaqueUserId: 'u_9ske45' - productIds: ['p_PJbnN', 'p_ojng4'] - objectType: 'listings' + examples: + - metrics: + ctr: true + opaqueUserId: u_9ske45 + productIds: + - p_PJbnN + - p_ojng4 + objectType: + - listings required: true responses: - 200: + '200': description: > - The prediction results. This will provide a numerical value for each combination of metric/product - requested on the API call. + The prediction results. This will provide a numerical value for + each combination of metric/product requested on the API call. content: application/json: schema: $ref: '#/components/schemas/PredictionResult' - example: - objectType: 'listings' + examples: + objectType: listings predictions: - - productId: 'p_PJbnN' + - productId: p_PJbnN ctr: 0.03 - - productId: 'p_ojng4' + - productId: p_ojng4 ctr: 0.056 error: false - 400: + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' - /toptimize/v1/retrieval: post: tags: - Toptimize summary: '[Beta] Retrieve objects' - description: | + description: > > ⚠️ **Beta Access Required** + > Contact your sales representative to gain access to this endpoint and start using it. + Use the `/retrieval` endpoint to get recommendations of which products are relevant given a + certain context. Context is provided by user information, plus seed products. This can be used + to retrieve object to display on a PDP (single seed product) or in a cart (multiple seed products). + In order to provide retrieval, Topsort requires that events are also sent, as a source of + information. operationId: retrieveObjects requestBody: - description: | - The context information for the predictions, including which metrics to predict. + description: > + The context information for the predictions, including which + metrics to predict. x-beta: 'true' content: application/json: schema: $ref: '#/components/schemas/RetrievalRequest' - example: + examples: slots: 5 - opaqueUserId: 'u_9ske45' - seedProductIds: ['p_PJbnN', 'p_ojng4'] + opaqueUserId: u_9ske45 + seedProductIds: + - p_PJbnN + - p_ojng4 mode: all - deviceType: mobile + deviceType: + - mobile required: true responses: - 200: + '200': description: > - The retrieval results. Each retrieved products is accompanied by their relevancy score. + The retrieval results. Each retrieved products is accompanied by + their relevancy score. content: application/json: schema: $ref: '#/components/schemas/RetrievalResults' - example: - objectType: 'listing' - objects: - - id: 'p_xh90s' + examples: + - objectType: listing + objects: + - id: p_xh90s value: 0.978 - - id: 'p_12lp0' + - id: p_12lp0 value: 0.953 - - id: 'p_ds7ui' + - id: p_ds7ui value: 0.877 - error: false - 400: + error: false + '400': $ref: '#/components/responses/BadRequest' - 401: + '401': $ref: '#/components/responses/UnauthorizedError' - components: responses: UnauthorizedError: @@ -657,7 +613,6 @@ components: application/json: schema: $ref: '#/components/schemas/Error' - schemas: Category: oneOf: @@ -670,37 +625,41 @@ components: properties: ids: type: array - description: | - An array containing the category IDs of the bids that will participate in an auction. + description: > + An array containing the category IDs of the bids that will + participate in an auction. + In order to participate in an auction, a bid product must belong to **all** of the categories provided in the auction request. items: type: string description: A category ID. minLength: 1 minItems: 1 - example: + examples: - c_men_clothing - c_shoes - type: object title: Category Disjunctions - description: Multiple disjunctions of categories for the purpose of running an auction. + description: + Multiple disjunctions of categories for the purpose of running an + auction. required: - disjunctions properties: disjunctions: type: array - description: | + description: > An array of disjunctions. + In order to participate in an auction, a bid product must belong to at least one of the categories of the disjunction provided in the auction request. items: $ref: '#/components/schemas/CategoryDisjunction' minItems: 1 maxItems: 5 - example: - - - c_red - - c_blue - + examples: + - c_red + - c_blue SingleCategory: type: object description: A category for the purpose of running an auction. @@ -711,20 +670,20 @@ components: type: string description: The category ID of the bids that will participate in an auction. minLength: 1 - example: c_yogurt - + examples: + - c_yogurt CategoryDisjunction: type: array - description: | + description: > An array of category IDs, describing a category disjunction. + A bid entity must belong to at least one of the categories in the disjunction in order to participate in the auction. items: type: string description: A category ID. minimum: 1 minItems: 1 - Device: type: string description: The device for which the ads are meant for. @@ -732,15 +691,14 @@ components: - desktop - mobile default: desktop - DeviceType: type: string description: The device the user is on. enum: - desktop - mobile - example: mobile - + examples: + - mobile Page: type: object title: Page @@ -758,50 +716,64 @@ components: - cart - other description: Type of page. - example: 'category' + examples: + - category value: oneOf: - type: string description: Detail of the page, depending on the type - example: 'electronics' + examples: + - electronics - type: array items: type: string description: Only valid for type cart. Items on the cart - example: '[ "coffee", "cookies", "apples" ]' + examples: + - coffee + - cookies + - apples minItems: 1 pageId: type: string description: Identifies the page - example: '/category/electronics' - + examples: + - /category/electronics OpaqueUserID: type: string description: - The opaque user ID is an anonymized unique identifier that maps to the original user ID without revealing the - original value. This identifier allows Topsort to correlate user activity between auctions and user - interactions, independent of the user's logged-in status. For apps or sites where users might interact while - logged out, we recommend generating a random identifier (UUIDv7) on the first load, storing it on local storage - (cookie, local storage, etc), and letting it live for at least a year. Otherwise, if your users are always - logged in for interactions, you may use a hash of your customer ID. Correct purchase attribution requires - long-lived opaque user IDs consistent between auction and event requests. - example: 71303ce0-de89-496d-8270-6434589615e8 - + The opaque user ID is an anonymized unique identifier that maps to + the original user ID without revealing the original value. This + identifier allows Topsort to correlate user activity between auctions + and user interactions, independent of the user's logged-in status. For + apps or sites where users might interact while logged out, we recommend + generating a random identifier (UUIDv7) on the first load, storing it on + local storage (cookie, local storage, etc), and letting it live for at + least a year. Otherwise, if your users are always logged in for + interactions, you may use a hash of your customer ID. Correct purchase + attribution requires long-lived opaque user IDs consistent between + auction and event requests. + examples: + - 71303ce0-de89-496d-8270-6434589615e8 PlacementId: type: integer format: int32 description: The marketplace's ID of the placement where the ad will appear. - GeoTargeting: type: object - description: An object describing geographical information associated with this auction. + description: + An object describing geographical information associated with this + auction. required: - location properties: location: description: The location this auction is being run for. type: string - + ResolvedBidID: + type: string + description: An opaque Topsort ID to be used when this item is interacted with. + examples: + - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= SponsoredListingsAuction: type: object description: | @@ -820,7 +792,9 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be returned. + description: + Specifies the maximum number of auction winners that should be + returned. category: $ref: '#/components/schemas/Category' searchQuery: @@ -837,24 +811,20 @@ components: required: - type - slots - example: - type: listings - slots: 2 - products: - ids: - - p_PJbnN - - p_ojng4 - - p_8VKDt - - p_Mfk15 - # category: - # id: c_yogurt - # searchQuery: Noosa Peach - geoTargeting: - location: New York - + examples: + - type: listings + slots: 2 + products: + ids: + - p_PJbnN + - p_ojng4 + - p_8VKDt + - p_Mfk15 + geoTargeting: + location: New York BannersAuction: type: object - description: | + description: > Describes the intent of running a banner ads auction. * For **Landing Page** banners, `category` and `searchQuery` must be empty. @@ -870,7 +840,9 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be returned. + description: + Specifies the maximum number of auction winners that should be + returned. category: $ref: '#/components/schemas/Category' searchQuery: @@ -882,7 +854,9 @@ components: $ref: '#/components/schemas/GeoTargeting' slotId: type: string - description: The ID of the banner placement for which this auction will be run for. + description: + The ID of the banner placement for which this auction will be run + for. minLength: 1 products: $ref: '#/components/schemas/Products' @@ -894,19 +868,17 @@ components: - type - slots - slotId - example: - type: banners - slots: 1 - slotId: categories-ribbon-banner - category: - id: c_yogurt - + examples: + - type: banners + slots: 1 + slotId: categories-ribbon-banner + category: + id: c_yogurt AuctionRequest: description: Describes the intent of running a single auction. oneOf: - $ref: '#/components/schemas/SponsoredListingsAuction' - $ref: '#/components/schemas/BannersAuction' - RankingRequest: type: object description: | @@ -921,12 +893,16 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of ranked objects that should be returned. + description: + Specifies the maximum number of ranked objects that should be + returned. pageSize: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of ranked objects per page that should be returned. + description: + Specifies the maximum number of ranked objects per page that should + be returned. page: $ref: '#/components/schemas/Page' category: @@ -938,37 +914,33 @@ components: products: $ref: '#/components/schemas/Products' opaqueUserId: - type: string - description: | - The opaque user ID allows correlating user activity, such as Impressions, Clicks and Purchases, - whether or not they are actually logged in. It must be long lived (at least a year) so that Topsort can attribute purchases. - If your users are always logged in you may use a hash of your customer ID. - If your users may interact with your app or site while logged out we - recommend generating a random identifier (UUIDv4) on first load and store it on - local storage (cookie, local storage, etc) and let it live for at least a year. - minLength: 1 - example: 71303ce0-de89-496d-8270-6434589615e8 + $ref: '#/components/schemas/OpaqueUserID' required: - type - slots - pageSize - page - opaqueUserId - example: - type: listings - slots: 10 - pageSize: 10 - category: - ids: ['sneakers', 'shoes'] - products: - ids: ['p_PJbnN', 'p_ojng4'] - + examples: + - type: listings + slots: 10 + pageSize: 10 + category: + ids: + - sneakers + - shoes + products: + ids: + - p_PJbnN + - p_ojng4 PredictionRequest: type: object properties: metrics: type: object - description: Metrics to predict, the response will include all the selected metrics. + description: + Metrics to predict, the response will include all the selected + metrics. properties: ctr: type: boolean @@ -977,12 +949,7 @@ components: type: boolean description: If `true` a Conversion Rate prediction will be made. opaqueUserId: - type: string - description: - The opaque user ID is an anonymized unique identifier that maps to the original user ID without revealing the - original value. This identifier allows Topsort to use interactions information to later on provide a prediction - of the outcome of the interaction between the user and a product. - example: 71303ce0-de89-496d-8270-6434589615e8 + $ref: '#/components/schemas/OpaqueUserID' page: $ref: '#/components/schemas/Page' objectType: @@ -997,29 +964,27 @@ components: type: array items: type: string - example: ['p_1234', 'p_5678'] + examples: + - p_1234 + - p_5678 required: - metrics - productIds - objectType - opaqueUserId - RetrievalRequest: type: object properties: slots: type: integer description: How many objects to retrieve. - example: 10 + examples: + - 10 + - 50 minimum: 1 maximum: 100 opaqueUserId: - type: string - description: - The opaque user ID is an anonymized unique identifier that maps to the original user ID without revealing the - original value. This identifier allows Topsort to use interactions information to later on provide a prediction - of the outcome of the interaction between the user and a product. - example: 71303ce0-de89-496d-8270-6434589615e8 + $ref: '#/components/schemas/OpaqueUserID' page: $ref: '#/components/schemas/Page' objectType: @@ -1034,7 +999,9 @@ components: type: array items: type: string - example: ['p_1234', 'p_5678'] + examples: + - p_1234 + - p_5678 mode: type: string description: Retrieval mode, how to interpret the context to get objects. @@ -1048,7 +1015,6 @@ components: - seedProductIds - opaqueUserId - objectType - AuctionResult: discriminator: propertyName: resultType @@ -1058,12 +1024,10 @@ components: oneOf: - $ref: '#/components/schemas/SponsoredListingsAuctionResult' - $ref: '#/components/schemas/BannersAuctionResult' - TravelAuctionResult: oneOf: - $ref: '#/components/schemas/HotelsAuctionResult' - $ref: '#/components/schemas/FlightsAuctionResult' - BannersAuctionResult: type: object properties: @@ -1074,17 +1038,18 @@ components: items: $ref: '#/components/schemas/BannersWinner' description: > - Array of winner objects in order from highest to lowest bid. - It will be empty if there were no qualifying bids or if there was an error. + Array of winner objects in order from highest to lowest bid. It + will be empty if there were no qualifying bids or if there was an + error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. - example: false + examples: + - false required: - winners - error - resultType - SponsoredListingsAuctionResult: type: object properties: @@ -1095,17 +1060,18 @@ components: items: $ref: '#/components/schemas/SponsoredListingsWinner' description: > - Array of winner objects in order from highest to lowest bid. - It will be empty if there were no qualifying bids or if there was an error. + Array of winner objects in order from highest to lowest bid. It + will be empty if there were no qualifying bids or if there was an + error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. - example: false + examples: + - false required: - winners - error - resultType - SponsoredListingsWinner: type: object required: @@ -1119,9 +1085,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. - One-based, so the product with rank 1 won the auction. - In an auction response, the winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the + product with rank 1 won the auction. In an auction response, the + winners array is sorted so rank will match the entry's index. minimum: 1 type: type: string @@ -1133,18 +1099,18 @@ components: - url id: type: string - description: |- - The marketplace's ID of the winning entity, depending on the target of the campaign. - example: p_Mfk15 + description: + The marketplace's ID of the winning entity, depending on the target + of the campaign. + examples: + - p_Mfk15 resolvedBidId: - type: string - description: An opaque Topsort ID to be used when this item is interacted with. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. - example: 4bcc6093-f367-4df2-aa1b-7c1674dd6441 - + examples: + - 4bcc6093-f367-4df2-aa1b-7c1674dd6441 BannersWinner: type: object required: @@ -1158,9 +1124,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. - One-based, so the product with rank 1 won the auction. - In an auction response, the winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the + product with rank 1 won the auction. In an auction response, the + winners array is sorted so rank will match the entry's index. minimum: 1 type: type: string @@ -1172,27 +1138,26 @@ components: - url id: type: string - description: |- - The marketplace's ID of the winning entity, depending on the target of the campaign. - example: p_Mfk15 + description: + The marketplace's ID of the winning entity, depending on the target + of the campaign. + examples: + - p_Mfk15 resolvedBidId: - type: string - description: An opaque Topsort ID to be used when this item is interacted with. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. - example: 4bcc6093-f367-4df2-aa1b-7c1674dd6441 + examples: + - 4bcc6093-f367-4df2-aa1b-7c1674dd6441 asset: description: The list of available sources for a banner. type: array items: $ref: '#/components/schemas/AssetSource' minItems: 1 - HotelsAuctionResult: $ref: '#/components/schemas/SponsoredListingsAuctionResult' - FlightsAuctionResult: type: object properties: @@ -1203,17 +1168,18 @@ components: items: $ref: '#/components/schemas/FlightsWinner' description: > - Array of winner objects in order from highest to lowest bid. - It will be empty if there were no qualifying bids or if there was an error. + Array of winner objects in order from highest to lowest bid. It + will be empty if there were no qualifying bids or if there was an + error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. - example: false + examples: + - false required: - winners - error - resultType - FlightsWinner: type: object required: @@ -1228,9 +1194,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. - One-based, so the product with rank 1 won the auction. - In an auction response, the winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the + product with rank 1 won the auction. In an auction response, the + winners array is sorted so rank will match the entry's index. minimum: 1 type: type: string @@ -1239,21 +1205,21 @@ components: - product id: type: string - description: |- - The marketplace's ID of the winning flight product, depending on the target of the campaign. - example: p_Mfk15 + description: + The marketplace's ID of the winning flight product, depending on + the target of the campaign. + examples: + - p_Mfk15 resolvedBidId: - type: string - description: An opaque Topsort ID to be used when this item is interacted with. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. - example: 4bcc6093-f367-4df2-aa1b-7c1674dd6441 + examples: + - 4bcc6093-f367-4df2-aa1b-7c1674dd6441 variationID: type: string description: The marketplace's ID for the winning flight product's variation. - RankingResult: type: object properties: @@ -1263,17 +1229,17 @@ components: type: array items: $ref: '#/components/schemas/RankingWinner' - description: > + description: | Array of ranking objects in order from highest to lowest relevancy. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. - example: false + examples: + - false required: - results - error - resultType - RankingWinner: type: object required: @@ -1285,7 +1251,7 @@ components: rank: type: integer format: int32 - description: > + description: | Where is the product ranked in the auction. minimum: 1 type: @@ -1296,14 +1262,14 @@ components: - sponsored id: type: string - description: |- - The marketplace's ID of the ranked entity. - example: p_Mfk15 + description: The marketplace's ID of the ranked entity. + examples: + - p_Mfk15 resolvedItemId: type: string description: An opaque Topsort ID to be used when this item is interacted with. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - + examples: + - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= PredictionResult: type: object properties: @@ -1327,12 +1293,11 @@ components: cvr: type: number description: Conversion Rate prediction. - description: > + description: | Predicted objects. required: - objectType - predictions - RetrievalResults: type: object properties: @@ -1353,12 +1318,11 @@ components: score: type: number description: Relevance score for the retrieved products. - description: > + description: | Retrieved objects. required: - objectType - objects - InteractionObject: type: object description: Information regarding an organic or non-sponsored event. @@ -1374,60 +1338,29 @@ components: assetId: type: string description: When type is `banner`, signals the ID of the asset of the banner - example: banner_asset_001 + examples: + - banner_asset_001 clickType: type: string - description: When type is `listing`, signals the specific interaction flavor with the listing. + description: + When type is `listing`, signals the specific interaction flavor + with the listing. enum: - product - like - add-to-cart - - # Dimensions: - # type: object - # description: The dimensions of this source. - # properties: - # width: - # type: integer - # format: int32 - # description: The source width in pixels. - # minimum: 1 - # height: - # type: integer - # format: int32 - # description: The source height in pixels. - # minimum: 1 - # required: - # - width - # - height - AssetSource: description: A source available for an asset (banner or video). type: object properties: - # mimeType: - # type: string - # description: The MIME type of this source. - # example: image/png - # dimensions: - # $ref: '#/components/schemas/Dimensions' - # fileSize: - # type: integer - # format: int32 - # description: The file size in bytes. - # example: 238490 url: type: string format: uri description: > - A vendor provided asset that the marketplace has to use as a banner. - The asset will be served by Topsort's CDN. + A vendor provided asset that the marketplace has to use as a + banner. The asset will be served by Topsort's CDN. required: - # - mimeType - # - dimensions - # - fileSize - url - Products: required: - ids @@ -1436,35 +1369,41 @@ components: ids: type: array description: > - An array of product IDs that should participate in the auction. - We recommend sending no more than 500 products per auction. + An array of product IDs that should participate in the auction. We + recommend sending no more than 500 products per auction. items: type: string description: > - The marketplace's ID of a product which will participate in the auction. - These ID must match those in the catalog integration with Topsort. - example: p_SA0238 + The marketplace's ID of a product which will participate in the + auction. These ID must match those in the catalog integration with + Topsort. + examples: + - p_SA0238 minLength: 1 minItems: 1 maxItems: 10000 qualityScores: type: array - description: | - An array of marketplace defined quality scores, each corresponding to the product ID with matching array index. + description: > + An array of marketplace defined quality scores, each corresponding + to the product ID with matching array index. + If given, these values will be combined with our internal quality scores to provide a score + that better represents the relevance of the participating products. + Note that the length of this array must be the same as the length of the `ids` array and + that the values must be between 0 and 1. items: type: number - minimum: 0 maximum: 1 - exclusiveMinimum: true - example: 0.75 + exclusiveMinimum: 0 + examples: + - 0.75 format: double minItems: 1 maxItems: 10000 - SponsoredBrandAuctionRequest: type: object description: | @@ -1482,7 +1421,9 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be returned. + description: + Specifies the maximum number of auction winners that should be + returned. placementId: type: string x-stoplight: @@ -1508,7 +1449,6 @@ components: ids: - '1' - '8' - SponsoredBrandAuctionResult: type: object properties: @@ -1516,12 +1456,15 @@ components: type: array items: $ref: '#/components/schemas/SponsoredBrandWinner' - description: | - Array of winner objects in order from highest to lowest bid. It will be empty if there were no qualifying bids or if there was an error. + description: > + Array of winner objects in order from highest to lowest bid. It + will be empty if there were no qualifying bids or if there was an + error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. - example: false + examples: + - false required: - winners - error @@ -1534,13 +1477,13 @@ components: productId: '1' title: Brand Example Promo 1 assets: - - url: 'https://assets.hosted.topsort.com/5bcccb92e5eaaa73ce9fcc545e944865bf70e9b60e5a048979769282450343c4/example-banner-1.png' + - url: https://assets.hosted.topsort.com/5bcccb92e5eaaa73ce9fcc545e944865bf70e9b60e5a048979769282450343c4/example-banner-1.png role: image contentType: image/png contentLength: 33902 width: 920 height: 920 - - url: 'https://assets.hosted.topsort.com/c27c9cd94badc90fb50827e144dfacb2f51a601560905b950f525cec725ea85f/example-logo-1.png' + - url: https://assets.hosted.topsort.com/c27c9cd94badc90fb50827e144dfacb2f51a601560905b950f525cec725ea85f/example-logo-1.png role: logo contentType: image/png contentLength: 80648 @@ -1552,13 +1495,13 @@ components: productId: '8' title: Brand Example Promo 2 assets: - - url: 'https://assets.hosted.topsort.com/c049a46d834ab071cdde63e401d4efcd554e1a124f05c4ba9b3743fed2d43c4b/example-banner-2.jpeg' + - url: https://assets.hosted.topsort.com/c049a46d834ab071cdde63e401d4efcd554e1a124f05c4ba9b3743fed2d43c4b/example-banner-2.jpeg role: image contentType: image/jpeg contentLength: 4505 width: 403 height: 125 - - url: 'https://assets.hosted.topsort.com/db41a8b8b22c5ed9091f9f154b552b6bc1d1dbeb85059190f1c3b202977938f1/example-logo-2.png' + - url: https://assets.hosted.topsort.com/db41a8b8b22c5ed9091f9f154b552b6bc1d1dbeb85059190f1c3b202977938f1/example-logo-2.png role: logo contentType: image/png contentLength: 34747 @@ -1566,7 +1509,6 @@ components: height: 160 campaignId: 01934a6e-7bb3-79c1-89b3-134e2e3bf88e error: false - SponsoredBrandWinner: type: object required: @@ -1579,33 +1521,38 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. - One-based, so the product with rank 1 won the auction. - In an auction response, the winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the + product with rank 1 won the auction. In an auction response, the + winners array is sorted so rank will match the entry's index. minimum: 1 productId: type: string - description: |- - The marketplace's ID of the winning entity, depending on the target of the campaign. - example: p_Mfk15 + description: + The marketplace's ID of the winning entity, depending on the target + of the campaign. + examples: + - p_Mfk15 resolvedBidId: type: string description: An opaque Topsort ID to be used when this item is interacted with. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + examples: + - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= title: type: string - description: An optional title for the sponsored brand selected when creating the campaign. + description: + An optional title for the sponsored brand selected when creating + the campaign. vendorId: type: string description: The ID of the vendor associated with this sponsored brand winner. - example: v_8fj2D + examples: + - v_8fj2D assets: description: Assets used to render the sponsored brand ad. type: array items: $ref: '#/components/schemas/SponsoredBrandAsset' minItems: 1 - SponsoredBrandAsset: type: object properties: @@ -1613,8 +1560,8 @@ components: type: string format: uri description: > - A vendor provided asset that the marketplace has to render. - The asset will be served by Topsort's CDN. + A vendor provided asset that the marketplace has to render. The + asset will be served by Topsort's CDN. role: type: string description: The role of the asset. It can be either `logo` or `image`. @@ -1633,13 +1580,11 @@ components: type: integer format: uint32 description: The asset height in pixels. - TravelAuctionRequest: description: Describes the intent of running a single auction. oneOf: - $ref: '#/components/schemas/HotelsAuctionRequest' - $ref: '#/components/schemas/FlightsAuctionRequest' - HotelsAuctionRequest: type: object description: Describes the intent of running a hotel travel auction. @@ -1655,7 +1600,9 @@ components: slots: type: integer format: int32 - description: Specifies the maximum number of auction winners that should be returned. If slots > 40, it is capped at 40. + description: + Specifies the maximum number of auction winners that should be + returned. If slots > 40, it is capped at 40. minimum: 1 maximum: 40 products: @@ -1677,10 +1624,10 @@ components: type: string description: The category ID of the bids that will participate in an auction. minLength: 1 - example: c_buenos-aires-hotels + examples: + - c_buenos-aires-hotels travelContext: $ref: '#/components/schemas/HotelsTravelContext' - HotelsTravelProduct: type: object required: @@ -1689,20 +1636,20 @@ components: id: type: string description: ID to identify hotel product. - example: miami-hotel + examples: + - miami-hotel qualityScore: type: number - minimum: 0 maximum: 1 - exclusiveMinimum: true - example: 0.75 + exclusiveMinimum: 0 + examples: + - 0.75 format: double description: | If given, this value will be combined with our internal quality score to provide a score that better represents the relevance of the participating products. If not given it will default to 1. Values must be between 0 and 1. - BaseTravelContext: type: object required: @@ -1713,22 +1660,27 @@ components: minLength: 1 maxLength: 64 description: Web site requesting the auction - example: argentina + examples: + - argentina passengers: type: integer description: Number of passengers. Must not exceed 10. - example: 3 + examples: + - 3 travelStartDate: type: string format: date description: RFC3339 formatted date representing the travel start point. - example: '2009-01-01' + examples: + - 2024-06-10 travelEndDate: type: string format: date - description: | - RFC3339 formatted date representing the travel end point. Must be greater than start date. - example: '2009-01-15' + description: > + RFC3339 formatted date representing the travel end point. Must be + greater than start date. + examples: + - 2025-08-10 travelerType: type: string enum: @@ -1742,11 +1694,9 @@ components: platform: type: string description: Platform e.g. "app", "mobile", "web", ... - HotelsTravelContext: allOf: - $ref: '#/components/schemas/BaseTravelContext' - FlightsAuctionRequest: type: object description: Describes the intent of running a flight travel auction. @@ -1762,7 +1712,9 @@ components: slots: type: integer format: int32 - description: Specifies the maximum number of auction winners that should be returned. If slots > 40, it is capped at 40. + description: + Specifies the maximum number of auction winners that should be + returned. If slots > 40, it is capped at 40. minimum: 1 maximum: 40 products: @@ -1772,7 +1724,6 @@ components: $ref: '#/components/schemas/FlightsTravelProduct' travelContext: $ref: '#/components/schemas/FlightsTravelContext' - FlightsTravelProduct: type: object required: @@ -1781,7 +1732,8 @@ components: id: type: string description: ID to identify flight product. - example: L0_SAO-ORL + examples: + - L0_SAO-ORL variationID: type: string description: ID to identify flight product variation. @@ -1790,17 +1742,16 @@ components: description: Flight product variation total price in marketplace currency. qualityScore: type: number - minimum: 0 maximum: 1 - exclusiveMinimum: true - example: 0.75 + exclusiveMinimum: 0 + examples: + - 0.75 format: double description: | If given, this value will be combined with our internal quality score to provide a score that better represents the relevance of the participating products. If not given it will default to 1. Values must be between 0 and 1. - FlightsTravelContext: allOf: - $ref: '#/components/schemas/BaseTravelContext' @@ -1812,7 +1763,6 @@ components: flightType: type: string description: Flight type e.g. "round_trip", "one_way", ... - Error: type: object required: @@ -1846,16 +1796,25 @@ components: - too_few_impressions - too_few_slots - too_many_auctions + examples: + - bad_request + - no_products docUrl: type: string format: uri - description: A link to a documentation page providing more information about the error. - example: https://docs.topsort.com/reference/errors + description: + A link to a documentation page providing more information about the + error. + examples: + - https://api.docs.topsort.com/reference/errors message: type: string description: > - Human-readable explanation of or details about the error. - The string for a given error may change over time; code should not parse or dispatch based on particular values for this field. + Human-readable explanation of or details about the error. The + string for a given error may change over time; code should not parse + or dispatch based on particular values for this field. + examples: + - could not find the provided resolved bid id Placement: type: object required: @@ -1864,38 +1823,41 @@ components: properties: path: type: string - description: | + description: > URL path of the page triggering the event. - For web apps, this can be obtained in JS using `window.location.pathname`. - For mobile apps, use the deep link for the current view, if available. Otherwise, encode the view from which the event occurred in your app as a path-like string (e.g. `/root/categories/:categoryId`). minLength: 1 - example: /categories/dairy + examples: + - /categories/dairy position: type: integer description: > - For components with multiple items - (i.e. search results, similar products, etc), - this should indicate the index of a given item within that list. + For components with multiple items (i.e. search results, similar + products, etc), this should indicate the index of a given item + within that list. minimum: 1 page: type: integer description: > - For paginated pages, this should indicate which page number triggered the event. + For paginated pages, this should indicate which page number + triggered the event. minimum: 1 pageSize: type: integer description: > - For paginated pages this should indicate how many items are in each result page. + For paginated pages this should indicate how many items are in each + result page. minimum: 1 - example: 15 + examples: + - 15 productId: type: string description: > - The ID of the product associated to the page in which this event occurred, if applicable. - This ID must match the ID provided through the catalog service. + The ID of the product associated to the page in which this event + occurred, if applicable. This ID must match the ID provided through + the catalog service. minLength: 1 categoryIds: type: array @@ -1904,21 +1866,26 @@ components: minLength: 1 description: A category ID. description: > - An array of IDs of the categories associated to the page in which this event occurred, if applicable. - These IDs must match the IDs provided through the catalog service. + An array of IDs of the categories associated to the page in which + this event occurred, if applicable. These IDs must match the IDs + provided through the catalog service. minItems: 1 searchQuery: type: string description: > - The search string provided by the user in the page where this event occurred, if applicable. - This search string must match the searchQuery field that was provided in the auction request (if provided). + The search string provided by the user in the page where this event + occurred, if applicable. This search string must match the + searchQuery field that was provided in the auction request (if + provided). minLength: 1 Entity: type: object description: > - `Entity` is meant for reporting organic events, not sponsored or promoted products. It refers to the object - involved in the organic interaction. But, in most cases, you won't need to fill in this object. Be aware that - if `resolvedBidId` has any value, `entity` will be disregarded. + `Entity` is meant for reporting organic events, not sponsored or + promoted products. It refers to the object involved in the organic + interaction. But, in most cases, you won't need to fill in this object. + Be aware that if `resolvedBidId` has any value, `entity` will be + disregarded. required: - id - type @@ -1963,10 +1930,10 @@ components: minItems: 1 maxItems: 50 minProperties: 1 - example: - impressions: + examples: + - impressions: - id: eb874c98-bf4d-40a9-ae6d-fcf4cecb535c - occurredAt: '2019-01-01T12:59:59-05:00' + occurredAt: 2019-01-01T12:59:59-05:00 opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 placement: path: /categories/dairy @@ -1977,9 +1944,9 @@ components: resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= deviceType: mobile channel: onsite - clicks: + - clicks: - id: b39d39ed-ea0e-4059-9d15-4990b39c85a2 - occurredAt: '2019-01-01T13:01:42-05:00' + occurredAt: 2019-01-01T13:01:42-05:00 opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 placement: path: /categories/dairy @@ -1990,7 +1957,7 @@ components: resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= deviceType: mobile channel: offsite - purchases: + - purchases: - id: 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 items: - productId: p_SA0238 @@ -1999,7 +1966,7 @@ components: vendorId: v_8fj2D - productId: p_oajf2D unitPrice: 1.49 - occurredAt: '2019-01-01T12:59:59-05:00' + occurredAt: 2019-01-01T12:59:59-05:00 opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 deviceType: desktop channel: onsite @@ -2009,12 +1976,12 @@ components: unitPrice: 119.95 quantity: 5 vendorId: v_8fj2D - occurredAt: '2019-01-01T13:59:59-05:00' + occurredAt: 2019-01-01T13:59:59-05:00 opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 channel: instore - pageviews: + - pageviews: - id: 8f648a8e-830c-4bb4-9d93-6ea80075ca82 - occurredAt: '2019-01-01T12:59:58-05:00' + occurredAt: 2019-01-01T12:59:58-05:00 opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 page: type: category @@ -2025,11 +1992,15 @@ components: Impression: type: object description: > - An impression means a promotable has become visible to the consumer. - For promoted entities, include the `resolvedBidId` field from the `/v2/auctions` response. - For unpromoted entities, include the `entity` field to describe what was seen. - In case you cannot send an impression when the product becomes visible, send us an impression event when the product was rendered in the HTML or, if that's also not possible, when your API returns the results. - It is important to select the most specific event so that your vendors have more accurate CTR metrics, which will allow them to better predict their campaigns. + An impression means a promotable has become visible to the + consumer. For promoted entities, include the `resolvedBidId` field from + the `/v2/auctions` response. For unpromoted entities, include the + `entity` field to describe what was seen. In case you cannot send an + impression when the product becomes visible, send us an impression event + when the product was rendered in the HTML or, if that's also not + possible, when your API returns the results. It is important to select + the most specific event so that your vendors have more accurate CTR + metrics, which will allow them to better predict their campaigns. required: - occurredAt - opaqueUserId @@ -2037,9 +2008,12 @@ components: additionalProperties: false properties: resolvedBidId: - type: string - description: If the impression is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + $ref: "#/components/schemas/ResolvedBidID" + description: > + If the impression is over an ad promotion, this is the + `resolvedBidId` field received from the `/auctions` request. In most + situations, especially when reporting a sponsored interaction, + you'll want to fill in this field. entity: $ref: '#/components/schemas/Entity' placement: @@ -2048,17 +2022,21 @@ components: type: string format: date-time description: RFC3339 formatted timestamp including UTC offset. - example: '2009-01-01T12:59:59-05:00' + examples: + - 2009-01-01T12:59:59-05:00 opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: type: string description: > - The marketplace's unique ID for the impression. - This field ensures the event reporting is idempotent in case there is a network issue and the request is retried. - If there is no impression model on the marketplace side, generate a unique string that does not change if the event is resent. + The marketplace's unique ID for the impression. This field ensures + the event reporting is idempotent in case there is a network issue + and the request is retried. If there is no impression model on the + marketplace side, generate a unique string that does not change if + the event is resent. minLength: 1 - example: eb874c98-bf4d-40a9-ae6d-fcf4cecb535c + examples: + - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c additionalAttribution: $ref: '#/components/schemas/Entity' page: @@ -2068,25 +2046,32 @@ components: externalCampaignId: type: string description: Marketplace provided ID for a campaign - example: 'awareness-campaign-2025' + examples: + - awareness-campaign-2025 externalVendorId: type: string description: Marketplace provided ID for a vendor - example: 'my-new-vendor' + examples: + - my-new-vendor deviceType: $ref: '#/components/schemas/DeviceType' channel: type: string description: Optional. The channel where the event occurred. - enum: ['onsite', 'offsite', 'instore'] - example: 'onsite' - + enum: + - onsite + - offsite + - instore + examples: + - onsite Click: description: > - A click is sent to Topsort when the consumer has clicked on a promotable. - For promoted entities, include the `resolvedBidId` field from the `/v2/auctions` response. - For unpromoted entities, include the `entity` field to describe what was clicked. - Topsort charges the vendor and pays the marketplace for clicks on ads in promoted placements on the marketplace app. + A click is sent to Topsort when the consumer has clicked on a + promotable. For promoted entities, include the `resolvedBidId` field + from the `/v2/auctions` response. For unpromoted entities, include the + `entity` field to describe what was clicked. Topsort charges the vendor + and pays the marketplace for clicks on ads in promoted placements on the + marketplace app. type: object required: - occurredAt @@ -2096,8 +2081,13 @@ components: properties: resolvedBidId: type: string - description: If the click is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. - example: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + description: + If the click is over an ad promotion, this is the `resolvedBidId` + field received from the `/auctions` request. In most situations, + especially when reporting a sponsored interaction, you'll want to + fill in this field. + examples: + - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= entity: $ref: '#/components/schemas/Entity' placement: @@ -2106,17 +2096,21 @@ components: type: string format: date-time description: RFC3339 formatted timestamp including UTC offset. - example: '2009-01-01T12:59:59-05:00' + examples: + - 2009-01-01T12:59:59-05:00 opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: type: string description: > - The marketplace's unique ID for the click. - This field ensures the event reporting is idempotent in case there is a network issue and the request is retried. - If there is no click model on the marketplace side, generate a unique string that does not change if the event is resent. + The marketplace's unique ID for the click. This field ensures the + event reporting is idempotent in case there is a network issue and + the request is retried. If there is no click model on the + marketplace side, generate a unique string that does not change if + the event is resent. minLength: 1 - example: b39d39ed-ea0e-4059-9d15-4990b39c85a2 + examples: + - b39d39ed-ea0e-4059-9d15-4990b39c85a2 additionalAttribution: $ref: '#/components/schemas/Entity' page: @@ -2125,7 +2119,9 @@ components: $ref: '#/components/schemas/InteractionObject' clickType: type: string - description: For sponsored events only, signals the specific interaction flavor with the listing. + description: + For sponsored events only, signals the specific interaction flavor + with the listing. enum: - product - like @@ -2133,23 +2129,29 @@ components: externalCampaignId: type: string description: Marketplace provided ID for a campaign - example: 'awareness-campaign-2025' + examples: + - awareness-campaign-2025 externalVendorId: type: string description: Marketplace provided ID for a vendor - example: 'my-new-vendor' + examples: + - my-new-vendor deviceType: $ref: '#/components/schemas/DeviceType' channel: type: string description: Optional. The channel where the event occurred. - enum: ['onsite', 'offsite', 'instore'] - example: 'onsite' - + enum: + - onsite + - offsite + - instore + examples: + - onsite Purchase: description: > - A purchase is sent to Topsort once a marketplace customer places an order. - These events are used to measure the effectiveness of an ad campaign. + A purchase is sent to Topsort once a marketplace customer places an + order. These events are used to measure the effectiveness of an ad + campaign. type: object required: - occurredAt @@ -2160,8 +2162,12 @@ components: properties: occurredAt: type: string - description: RFC3339 formatted timestamp, including UTC offset, of the instant in which the order was placed. Please note that purchases will NOT be attributed to an auction that happened after. - example: '2021-10-12T07:20:50.52Z' + description: + RFC3339 formatted timestamp, including UTC offset, of the instant + in which the order was placed. Please note that purchases will NOT + be attributed to an auction that happened after. + examples: + - 2021-10-12T07:20:50.52Z format: date-time opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' @@ -2174,18 +2180,25 @@ components: id: type: string description: > - The marketplace unique ID for the order. - This field ensures the event reporting is idempotent in case there is a network issue and the request is retried. - If there is no unique ID for orders on the marketplace side, generate a unique string that does not change if the event needs to be resent. + The marketplace unique ID for the order. This field ensures the + event reporting is idempotent in case there is a network issue and + the request is retried. If there is no unique ID for orders on the + marketplace side, generate a unique string that does not change if + the event needs to be resent. minLength: 1 - example: 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 + examples: + - 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 deviceType: $ref: '#/components/schemas/DeviceType' channel: type: string description: Optional. The channel where the event occurred. - enum: ['onsite', 'offsite', 'instore'] - example: 'onsite' + enum: + - onsite + - offsite + - instore + examples: + - onsite PurchaseItem: type: object required: @@ -2197,33 +2210,38 @@ components: type: string description: The marketplace ID of the product being purchased. minLength: 1 - example: p_SA0238 + examples: + - p_SA0238 quantity: type: integer minimum: 1 default: 1 - description: Count of products purchased. - example: 2 + description: Amount of products purchased. + examples: + - 2 unitPrice: type: number format: double - minimum: 0.0 - exclusiveMinimum: true + exclusiveMinimum: 0 description: The price of a single item in the marketplace currency. - example: 12.95 + examples: + - 12.95 vendorId: type: string description: > - The vendor ID of the product being purchased. This field is optional - and should be filled in if 1. a product is sold by multiple vendors, or - 2. you want to use it for halo attribution + The vendor ID of the product being purchased. This field is + optional and should be filled in if 1. a product is sold by multiple + vendors, or 2. you want to use it for halo attribution minLength: 1 - example: v_8fj2D + examples: + - v_8fj2D Pageview: type: object description: > - A page view represents the navigation of the user throughout the page. They are considered organic events. - In contrast to clicks or impressions, which are events within a page, a page view is the interaction with the full page, which can contain multiple objects. + A page view represents the navigation of the user throughout the + page. They are considered organic events. In contrast to clicks or + impressions, which are events within a page, a page view is the + interaction with the full page, which can contain multiple objects. required: - occurredAt - opaqueUserId @@ -2237,26 +2255,33 @@ components: type: string format: date-time description: RFC3339 formatted timestamp including UTC offset. - example: '2009-01-01T12:59:59-05:00' + examples: + - 2009-01-01T12:59:59-05:00 opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: type: string description: > - The marketplace's unique ID for the event. - This field ensures the event reporting is idempotent in case there is a network issue and the request is retried. - If there is no pageview model on the marketplace side, generate a unique string that does not change if the event is resent. + The marketplace's unique ID for the event. This field ensures the + event reporting is idempotent in case there is a network issue and + the request is retried. If there is no pageview model on the + marketplace side, generate a unique string that does not change if + the event is resent. minLength: 1 - example: eb874c98-bf4d-40a9-ae6d-fcf4cecb535c + examples: + - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c deviceType: $ref: '#/components/schemas/DeviceType' channel: type: string description: Optional. The channel where the event occurred. - enum: ['onsite', 'offsite', 'instore'] - example: 'onsite' - + enum: + - onsite + - offsite + - instore + examples: + - onsite securitySchemes: - BearerAuth: + HTTPBearer: type: http scheme: bearer From 2ff92b31c599343fdc80f02f13b5784ae0acf860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 13:52:32 +1000 Subject: [PATCH 02/32] chore: add github workflows validation --- .github/workflows/lint-vacuum.yml | 2 +- .github/workflows/validate-github-actions.yml | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/validate-github-actions.yml diff --git a/.github/workflows/lint-vacuum.yml b/.github/workflows/lint-vacuum.yml index 9efea41..372e0e6 100644 --- a/.github/workflows/lint-vacuum.yml +++ b/.github/workflows/lint-vacuum.yml @@ -21,4 +21,4 @@ jobs: uses: pb33f/vacuum-action@v2 with: openapi_path: "topsort-api-v2.yml" - github_token: ${{ secrets.GITHUB_TOKEN } + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml new file mode 100644 index 0000000..cb57ab3 --- /dev/null +++ b/.github/workflows/validate-github-actions.yml @@ -0,0 +1,19 @@ +name: Lint +on: + pull_request: + +jobs: + actionlint: + name: Actionlint + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Actionlint + env: + version: "1.7.7" + run: curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin actionlint + - name: Run Actionlint + run: | + echo "::add-matcher::.github/matchers/actionlint.json" + actionlint -color From ca856bdfef7be0402ee24cf378e502f76e1a4a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 14:01:10 +1000 Subject: [PATCH 03/32] fix: add missing matcher --- .github/matcher-actionlint.json | 17 +++++++++++++++++ .github/workflows/validate-github-actions.yml | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .github/matcher-actionlint.json diff --git a/.github/matcher-actionlint.json b/.github/matcher-actionlint.json new file mode 100644 index 0000000..7d39109 --- /dev/null +++ b/.github/matcher-actionlint.json @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "actionlint", + "pattern": [ + { + "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] +} diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index cb57ab3..6b99fd2 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -15,5 +15,5 @@ jobs: run: curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin actionlint - name: Run Actionlint run: | - echo "::add-matcher::.github/matchers/actionlint.json" + echo "::add-matcher::.github/matchers-actionlint.json" actionlint -color From a02f8cfc4b9733bd09d1fea2614320a38f9e27b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 14:01:51 +1000 Subject: [PATCH 04/32] fix: matcher --- .github/workflows/validate-github-actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index 6b99fd2..7d2247c 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -15,5 +15,5 @@ jobs: run: curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin actionlint - name: Run Actionlint run: | - echo "::add-matcher::.github/matchers-actionlint.json" + echo "::add-matcher::.github/matcher-actionlint.json" actionlint -color From 2b259167619503661e582ad3a620f110f5978336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 14:03:10 +1000 Subject: [PATCH 05/32] fix: prettier --- topsort-api-v2.yml | 248 ++++++++++++++++++++++----------------------- 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 7ece3d1..4e6d231 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -93,38 +93,38 @@ paths: - results examples: - results: - - winners: - - rank: 1 - type: product - id: p_Mfk11 - resolvedBidId: WyJiX01mazExIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTMyNjYtY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0== - campaignId: 82588593-85c5-47c0-b125-07e315b7f2b3 - error: false + - winners: + - rank: 1 + type: product + id: p_Mfk11 + resolvedBidId: WyJiX01mazExIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTMyNjYtY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0== + campaignId: 82588593-85c5-47c0-b125-07e315b7f2b3 + error: false - results: - - winners: - - rank: 1 - type: product - id: p_Mfk15 - resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - campaignId: 4bcc6093-f367-4df2-aa1b-7c1674dd6441 - - rank: 2 - type: product - id: p_PJbnN - resolvedBidId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - campaignId: a72e4e43-55b5-4d08-81bb-cbb57df59c72 - error: false - - winners: - - rank: 1 - type: product - id: p_PJbnN - resolvedBidId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwiYmFubmVyQWRzIiwiZGVmYXVsdCIsIiJd - campaignId: 1156ef4e-0109-4190-ac97-4436c82358d2 - asset: - - url: https://topsort.cdnprovider.com/lhs-banner-image-for-p_PJbnN-1x.png - error: false + - winners: + - rank: 1 + type: product + id: p_Mfk15 + resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + campaignId: 4bcc6093-f367-4df2-aa1b-7c1674dd6441 + - rank: 2 + type: product + id: p_PJbnN + resolvedBidId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + campaignId: a72e4e43-55b5-4d08-81bb-cbb57df59c72 + error: false + - winners: + - rank: 1 + type: product + id: p_PJbnN + resolvedBidId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwiYmFubmVyQWRzIiwiZGVmYXVsdCIsIiJd + campaignId: 1156ef4e-0109-4190-ac97-4436c82358d2 + asset: + - url: https://topsort.cdnprovider.com/lhs-banner-image-for-p_PJbnN-1x.png + error: false - results: - - winners: [] - error: false + - winners: [] + error: false '400': $ref: '#/components/responses/BadRequest' '401': @@ -426,17 +426,17 @@ paths: - ranking examples: - ranking: - - type: listings - slots: 3 - pageSize: 3 - category: - ids: - - sneakers - - shoes - products: - ids: - - p_PJbnN - - p_ojng4 + - type: listings + slots: 3 + pageSize: 3 + category: + ids: + - sneakers + - shoes + products: + ids: + - p_PJbnN + - p_ojng4 required: true responses: '201': @@ -459,20 +459,20 @@ paths: - results examples: - results: - - products: - - rank: 1 - type: organic - id: p_Mfk11 - resolvedItemId: WyJiX01mazExIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTMyNjYtY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0== - - rank: 2 - type: sponsored - id: p_Mfk15 - resolvedItemId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - - rank: 3 - type: organic - id: p_PJbnN - resolvedItemId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - error: false + - products: + - rank: 1 + type: organic + id: p_Mfk11 + resolvedItemId: WyJiX01mazExIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTMyNjYtY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0== + - rank: 2 + type: sponsored + id: p_Mfk15 + resolvedItemId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + - rank: 3 + type: organic + id: p_PJbnN + resolvedItemId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + error: false '400': $ref: '#/components/responses/BadRequest' '401': @@ -592,12 +592,12 @@ paths: examples: - objectType: listing objects: - - id: p_xh90s - value: 0.978 - - id: p_12lp0 - value: 0.953 - - id: p_ds7ui - value: 0.877 + - id: p_xh90s + value: 0.978 + - id: p_12lp0 + value: 0.953 + - id: p_ds7ui + value: 0.877 error: false '400': $ref: '#/components/responses/BadRequest' @@ -670,7 +670,7 @@ components: type: string description: The category ID of the bids that will participate in an auction. minLength: 1 - examples: + examples: - c_yogurt CategoryDisjunction: type: array @@ -697,7 +697,7 @@ components: enum: - desktop - mobile - examples: + examples: - mobile Page: type: object @@ -736,7 +736,7 @@ components: pageId: type: string description: Identifies the page - examples: + examples: - /category/electronics OpaqueUserID: type: string @@ -1105,7 +1105,7 @@ components: examples: - p_Mfk15 resolvedBidId: - $ref: "#/components/schemas/ResolvedBidID" + $ref: '#/components/schemas/ResolvedBidID' campaignId: type: string description: The ID of the campaign that won the auction. @@ -1144,7 +1144,7 @@ components: examples: - p_Mfk15 resolvedBidId: - $ref: "#/components/schemas/ResolvedBidID" + $ref: '#/components/schemas/ResolvedBidID' campaignId: type: string description: The ID of the campaign that won the auction. @@ -1175,7 +1175,7 @@ components: type: boolean description: A boolean indicating whether this auction was resolved successfully. examples: - - false + - false required: - winners - error @@ -1211,7 +1211,7 @@ components: examples: - p_Mfk15 resolvedBidId: - $ref: "#/components/schemas/ResolvedBidID" + $ref: '#/components/schemas/ResolvedBidID' campaignId: type: string description: The ID of the campaign that won the auction. @@ -1377,7 +1377,7 @@ components: The marketplace's ID of a product which will participate in the auction. These ID must match those in the catalog integration with Topsort. - examples: + examples: - p_SA0238 minLength: 1 minItems: 1 @@ -1932,63 +1932,63 @@ components: minProperties: 1 examples: - impressions: - - id: eb874c98-bf4d-40a9-ae6d-fcf4cecb535c - occurredAt: 2019-01-01T12:59:59-05:00 - opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 - placement: - path: /categories/dairy - position: 1 - page: 1 - pageSize: 15 - categoryId: 9BLIe - resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - deviceType: mobile - channel: onsite + - id: eb874c98-bf4d-40a9-ae6d-fcf4cecb535c + occurredAt: 2019-01-01T12:59:59-05:00 + opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 + placement: + path: /categories/dairy + position: 1 + page: 1 + pageSize: 15 + categoryId: 9BLIe + resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + deviceType: mobile + channel: onsite - clicks: - - id: b39d39ed-ea0e-4059-9d15-4990b39c85a2 - occurredAt: 2019-01-01T13:01:42-05:00 - opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 - placement: - path: /categories/dairy - position: 1 - page: 1 - pageSize: 15 - categoryId: 9BLIe - resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= - deviceType: mobile - channel: offsite + - id: b39d39ed-ea0e-4059-9d15-4990b39c85a2 + occurredAt: 2019-01-01T13:01:42-05:00 + opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 + placement: + path: /categories/dairy + position: 1 + page: 1 + pageSize: 15 + categoryId: 9BLIe + resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + deviceType: mobile + channel: offsite - purchases: - - id: 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 - items: - - productId: p_SA0238 - unitPrice: 12.95 - quantity: 2 - vendorId: v_8fj2D - - productId: p_oajf2D - unitPrice: 1.49 - occurredAt: 2019-01-01T12:59:59-05:00 - opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 - deviceType: desktop - channel: onsite - - id: b7147656-504f-4ae7-b335-740829ff64c6 - items: - - productId: p_SA0279 - unitPrice: 119.95 - quantity: 5 - vendorId: v_8fj2D - occurredAt: 2019-01-01T13:59:59-05:00 - opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 - channel: instore + - id: 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 + items: + - productId: p_SA0238 + unitPrice: 12.95 + quantity: 2 + vendorId: v_8fj2D + - productId: p_oajf2D + unitPrice: 1.49 + occurredAt: 2019-01-01T12:59:59-05:00 + opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 + deviceType: desktop + channel: onsite + - id: b7147656-504f-4ae7-b335-740829ff64c6 + items: + - productId: p_SA0279 + unitPrice: 119.95 + quantity: 5 + vendorId: v_8fj2D + occurredAt: 2019-01-01T13:59:59-05:00 + opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 + channel: instore - pageviews: - - id: 8f648a8e-830c-4bb4-9d93-6ea80075ca82 - occurredAt: 2019-01-01T12:59:58-05:00 - opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 - page: - type: category - pageId: /categories/dairy - value: dairy - deviceType: mobile - channel: onsite + - id: 8f648a8e-830c-4bb4-9d93-6ea80075ca82 + occurredAt: 2019-01-01T12:59:58-05:00 + opaqueUserId: 71303ce0-de89-496d-8270-6434589615e8 + page: + type: category + pageId: /categories/dairy + value: dairy + deviceType: mobile + channel: onsite Impression: type: object description: > @@ -2008,7 +2008,7 @@ components: additionalProperties: false properties: resolvedBidId: - $ref: "#/components/schemas/ResolvedBidID" + $ref: '#/components/schemas/ResolvedBidID' description: > If the impression is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most From 51a15ca0b178e3390a01ce687bd1fad85a6fbe51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 14:22:04 +1000 Subject: [PATCH 06/32] chore: rename job --- .github/workflows/lint-vacuum.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint-vacuum.yml b/.github/workflows/lint-vacuum.yml index 372e0e6..16be47c 100644 --- a/.github/workflows/lint-vacuum.yml +++ b/.github/workflows/lint-vacuum.yml @@ -1,4 +1,4 @@ -name: "Lint OpenAPI spec with vacuum" +name: OpenAPI on: pull_request: @@ -9,7 +9,7 @@ permissions: jobs: vacuum-lint: - name: Run OpenAPI linting with vacuum + name: Validate with Vacuum runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From cecf60837683acfd12ed9a407a051cacfa825c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 15:01:18 +1000 Subject: [PATCH 07/32] chore: remove old files --- .github/workflows/lint-vacuum.yml | 4 +- catalog-crud-api.yml | 566 ------------------------------ topsort-catalog-service.yml | 488 -------------------------- 3 files changed, 2 insertions(+), 1056 deletions(-) delete mode 100644 catalog-crud-api.yml delete mode 100644 topsort-catalog-service.yml diff --git a/.github/workflows/lint-vacuum.yml b/.github/workflows/lint-vacuum.yml index 16be47c..134acb8 100644 --- a/.github/workflows/lint-vacuum.yml +++ b/.github/workflows/lint-vacuum.yml @@ -9,7 +9,7 @@ permissions: jobs: vacuum-lint: - name: Validate with Vacuum + name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -17,7 +17,7 @@ jobs: - name: Check Formatting run: npx prettier --check topsort-api-v2.yml - - name: Run OpenAPI lint with vacuum + - name: Validate with Vacuum uses: pb33f/vacuum-action@v2 with: openapi_path: "topsort-api-v2.yml" diff --git a/catalog-crud-api.yml b/catalog-crud-api.yml deleted file mode 100644 index 1507fbd..0000000 --- a/catalog-crud-api.yml +++ /dev/null @@ -1,566 +0,0 @@ -openapi: 3.0.2 -info: - title: Catalog API - version: 0.1.1 - description: Integration API to sync your catalog with Topsort. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - x-logo: - url: https://assets.website-files.com/61a717c57f45d64e5e24eebf/61ee6ccc3f6a684756ef6dec_logo.svg - backgroundColor: '#fff' - altText: Topsort -servers: - - url: https://central-services.api.sandbox.topsort.ai/public/v1/catalog-search-service - description: Sandbox server -security: - - HTTPBearer: [] -paths: - /catalogs/categories: - get: - tags: - - Categories API - summary: List Categories - operationId: list_categories - parameters: - - $ref: '#/components/parameters/offset' - - $ref: '#/components/parameters/limit' - responses: - '200': - description: The paginated list of categories. - content: - application/json: - schema: - $ref: '#/components/schemas/CategoryPage' - put: - tags: - - Categories API - summary: Upsert Categories - description: > - Creates the categories passed in the body. - If a category with the same ID already exists, the new content will completely replace the previous contents - (i.e. the result is the same as deleting any categories with the IDs that were passed in the request and then creating them from scratch). - operationId: upsert_categories - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Categories' - required: true - responses: - '204': - description: The categories were stored successfully. - '422': - description: Validation Error. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - security: - - HTTPBearer: [] - delete: - tags: - - Categories API - summary: Delete Categories - operationId: delete_categories_by_id - responses: - '204': - description: The categories with provided IDs were deleted. - '404': - description: One or more provided category IDs were not present. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - # '409': - # description: One or more provided category IDs are associated to one or more products. - # content: - # application/json: - # schema: - # $ref: '#/components/schemas/HTTPConflictError' - security: - - HTTPBearer: [] - /catalogs/categories/{categoryId}: - get: - tags: - - Categories API - summary: Get Category - operationId: get_category_by_id - parameters: - - required: true - schema: - title: Category ID - description: The ID of the category to fetch. - type: string - name: categoryId - in: path - responses: - '200': - description: The requested category. - content: - application/json: - schema: - $ref: '#/components/schemas/Category' - '404': - description: No category exists with the provided ID. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - security: - - HTTPBearer: [] - /catalogs/products: - get: - tags: - - Products API - summary: List Products - operationId: list_products - parameters: - - $ref: '#/components/parameters/offset' - - $ref: '#/components/parameters/limit' - responses: - '200': - description: The paginated list of products. - content: - application/json: - schema: - $ref: '#/components/schemas/ProductPage' - put: - tags: - - Products API - summary: Upsert Products - description: > - Creates the products passed in the body. - If a product with the same ID already exists, the new content will completely replace the previous contents - (i.e. the result is the same as deleting any products with the IDs that were passed in the request and then creating them from scratch). - operationId: upsert_products - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Products' - required: true - responses: - '204': - description: The products were stored successfully. - '422': - description: Validation Error. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - security: - - HTTPBearer: [] - delete: - tags: - - Products API - summary: Delete Products - operationId: delete_products_by_id - responses: - '204': - description: The products with provided IDs were deleted. - '404': - description: One or more provided product IDs were not present. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - /catalogs/products/{productId}: - get: - tags: - - Products API - summary: Get Product - operationId: get_product_by_id - parameters: - - required: true - schema: - title: Product ID - description: The ID of the product to fetch. - type: string - name: productId - in: path - responses: - '200': - description: The requested product. - content: - application/json: - schema: - $ref: '#/components/schemas/Product' - '404': - description: No product exists with the provided ID. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - security: - - HTTPBearer: [] - /catalogs/vendors: - get: - tags: - - Vendors API - summary: List Vendors - operationId: list_vendors - parameters: - - $ref: '#/components/parameters/offset' - - $ref: '#/components/parameters/limit' - responses: - '200': - description: The paginated list of vendors. - content: - application/json: - schema: - $ref: '#/components/schemas/VendorPage' - put: - tags: - - Vendors API - summary: Upsert Vendors - description: > - Creates the vendors passed in the body. - If a vendor with the same ID already exists, the new content will completely replace the previous contents - (i.e. the result is the same as deleting any vendors with the IDs that were passed in the request and then creating them from scratch). - operationId: upsert_vendors - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Vendors' - required: true - responses: - '204': - description: The vendors were stored successfully. - '422': - description: Validation Error. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - security: - - HTTPBearer: [] - delete: - tags: - - Vendors API - summary: Delete Vendors - operationId: delete_vendors_by_id - responses: - '204': - description: The vendors with provided IDs were deleted. - '404': - description: One or more provided vendors IDs were not present. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - /catalogs/vendors/{vendorId}: - get: - tags: - - Vendors API - summary: Get Vendor - operationId: get_vendor_by_id - parameters: - - required: true - schema: - title: Vendor ID - description: The ID of the vendor to fetch. - type: string - name: vendorId - in: path - responses: - '200': - description: The requested vendor. - content: - application/json: - schema: - $ref: '#/components/schemas/Vendor' - '404': - description: No vendor exists with the provided ID. - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPNotFoundError' - security: - - HTTPBearer: [] -components: - schemas: - Category: - type: object - properties: - id: - description: > - The category ID. - If there is no ID for categories in the marketplace, - this can be the category name as long as it is unique. - type: string - minLength: 1 - example: ahEDqV5uhjj8 - name: - description: The category name. - type: string - minLength: 1 - example: Beers/Belgian - parentId: - description: > - The ID of the parent category. - This model assumes each category can at most one parent category. - In this example, `bneEmHKG2yUe` could be a reference to the `Beers` category. - type: string - minLength: 1 - example: bneEmHKG2yUe - required: - - id - - name - Categories: - type: object - properties: - categories: - description: The categories to create or substitute. - type: array - items: - $ref: '#/components/schemas/Category' - minLength: 1 - required: - - categories - CategoryPage: - title: Category page - type: object - properties: - next: - $ref: '#/components/schemas/Next' - response: - description: Array of categories. - type: array - items: - $ref: '#/components/schemas/Category' - required: - - next - - response - Next: - type: object - nullable: true - example: null - properties: - offset: - title: Offset - description: How many items to skip from the beginning of the list. - type: integer - format: int32 - limit: - title: Limit - description: How many items to return. - type: integer - format: int32 - Product: - type: object - properties: - id: - description: The product ID. - type: string - minLength: 1 - example: eyGqR4YQgBJa - name: - description: The product name. - type: string - minLength: 1 - example: Delirium Tremens Beer Bottle 330cc x6 - description: - description: The product description. - type: string - minLength: 1 - example: > - Named as "Best Beer in the World" in 2008 at the World Beer Championships in Chicago, Illinois. - vendors: - description: The vendor IDs. - type: array - items: - type: string - minLength: 1 - minLength: 1 - example: - - 9SiwYqqL8vdG - categories: - description: The category IDs. - type: array - items: - type: string - minLength: 1 - minLength: 1 - example: - - ahEDqV5uhjj8 - imageURL: - description: > - The product image URL. - Its size should be between 250x250 and 600x600 pixels. - This is recommended in case the Topsort UI will be used to manage campaigns. - type: string - format: uri - example: https://r.btcdn.co/r/eyJzaG9wX2lkIjozMzU4LCJnIjoiMjYweCJ9/1759e16e6314a24/669830-Cerveza_Delirium_Tremens_Botella_330cc_x6.png - price: - description: The product price in the configured currency. - type: number - format: double - minimum: 0.0 - exclusiveMinimum: true - example: 18.99 - brand: - description: The product brand information. - type: object - properties: - id: - type: string - description: The brand ID. - example: es5086vyV - name: - type: string - description: The brand name. - example: Delirium - required: - - id - - name - required: - - id - - name - - description - - vendors - - categories - - brand - - price - - imageURL - Products: - type: object - properties: - products: - description: The products to create or substitute. - type: array - items: - $ref: '#/components/schemas/Product' - minLength: 1 - required: - - products - ProductPage: - title: Product page - type: object - properties: - next: - $ref: '#/components/schemas/Next' - response: - description: Array of products. - type: array - items: - $ref: '#/components/schemas/Product' - required: - - next - - response - Vendor: - title: Vendor - type: object - properties: - id: - description: > - The vendor ID. - If there is no ID for vendors in the marketplace, - this can be the vendor name as long as it is unique. - type: string - minLength: 1 - example: 9SiwYqqL8vdG - name: - description: The vendor name. - type: string - minLength: 1 - example: Huyghe Brewery - imageURL: - description: > - The vendor logo. - Its size should be between 250x250 and 600x600 pixels. - This is recommended in case the Topsort UI will be used to manage campaigns. - type: string - format: uri - example: https://r.btcdn.co/r/eyJzaG9wX2lkIjozMzU4LCJnIjoiMjYweCJ9/1759e16e6314a24/669830-Cerveza_Delirium_Tremens_Botella_330cc_x6.png - required: - - id - - name - Vendors: - type: object - properties: - vendors: - description: The vendors to create or substitute. - type: array - items: - $ref: '#/components/schemas/Vendor' - minLength: 1 - required: - - vendors - VendorPage: - title: Vendor page - type: object - properties: - next: - $ref: '#/components/schemas/Next' - response: - description: Array of vendors. - type: array - items: - $ref: '#/components/schemas/Vendor' - required: - - next - - response - HTTPNotFoundError: - title: HTTP Not Found Error - required: - - msg - type: object - properties: - msg: - title: Message - type: string - HTTPValidationError: - title: HTTP Validation Error - required: - - msg - type: object - properties: - msg: - title: Message - type: string - example: Entity not found. - securitySchemes: - HTTPBearer: - type: http - scheme: bearer - parameters: - offset: - in: query - name: offset - schema: - type: integer - format: int32 - description: > - An integer indicating how many items to skip from the beginning of the list of entities. - You may provide the value returned in the `next` field from the response of a previous page. - If not present, values will be returned from the start. - limit: - in: query - name: limit - schema: - type: integer - format: int32 - maximum: 100 - description: > - An integer indicating how many items will be returned taking the `offset` into account. - You may provide the value returned in the `next` field from the response of a previous page. -tags: - - name: Categories API - description: 'CRUD API to manage category entities' - - name: Products API - description: 'CRUD API to manage product entities' - - name: Vendors API - description: 'CRUD API to manage vendor entities' - - name: Models - x-displayName: Catalog Models - description: | - ## Category - - - ## Product - - - ## Vendor - diff --git a/topsort-catalog-service.yml b/topsort-catalog-service.yml deleted file mode 100644 index d7d5620..0000000 --- a/topsort-catalog-service.yml +++ /dev/null @@ -1,488 +0,0 @@ -openapi: 3.0.1 -info: - title: Topsort Reference Catalog API - contact: - email: ralonso@topsort.com - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - version: 1.0.0 - x-logo: - url: https://assets.topsort.com/Topsort_logo_icon_dark.svg - backgroundColor: '#fff' - altText: Topsort - description: Integration for Marketplaces' catalog queries - -servers: - - url: https://{marketplaceDomain} - variables: - marketplaceDomain: - default: demo.topsort.com/topsort/api - description: A URL that points to your catalog service - -tags: - - name: Catalog - description: Integration for Marketplaces' catalog queries. - - name: Models - x-displayName: All Models - description: | - ## Brand - - - ## Category - - - ## GetProductsByID Request - - - ## GetProductsByID Response - - - ## Paginated Brands Response - - - ## Paginated Categories Response - - - ## Paginated Products Response - - - ## Paginated Response - - - ## Paginated Vendors Response - - - ## Product - - - ## Vendor - - -security: - - BearerAuth: [] - -paths: - /: - get: - tags: - - Catalog - operationId: healthCheck - security: [] # No security - summary: Health Check - responses: - 200: - description: The service is up and ready to accept requests. - - /products: - post: - tags: - - Catalog - summary: Retrieves products by IDs - operationId: getProductsByID - requestBody: - description: An array of product IDs. - content: - application/json: - schema: - $ref: '#/components/schemas/GetProductsByIDRequest' - required: true - responses: - 200: - description: Returns the products' details, if available. - content: - application/json: - schema: - $ref: '#/components/schemas/GetProductsByIDResponse' - 401: - $ref: '#/components/responses/UnauthorizedError' - - /products/search: - get: - tags: - - Catalog - summary: Searches products - operationId: searchProducts - parameters: - - in: query - name: search - schema: - type: string - example: delirium tremens - description: > - The search string provided by the user. When a blank string is provided, - the string should match all products (e.g. all products with a given category ID). - required: true - - in: query - name: vendorID - schema: - type: string - minLength: 1 - example: '9SiwYqqL8vdG' - description: > - Vendor unique identifier. This identifier is given by the marketplace and allows this service - to match the vendor with the proper products. - required: false - - in: query - name: categoryID - schema: - type: string - minLength: 1 - example: ahEDqV5uhjj8 - description: Only retrieve products whose category matches the provided ID. - - $ref: '#/components/parameters/nextParam' - responses: - 200: - description: Returns products' details for the provided search terms if available, separated in pages. - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedProductsResponse' - 401: - $ref: '#/components/responses/UnauthorizedError' - - /categories: - get: - tags: - - Catalog - summary: Retrieves categories - operationId: getCategories - parameters: - - $ref: '#/components/parameters/nextParam' - responses: - 200: - description: Returns a complete list of categories, separated in pages. - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedCategoriesResponse' - 401: - $ref: '#/components/responses/UnauthorizedError' - - /vendors: - get: - tags: - - Catalog - summary: Retrieves vendors - operationId: getVendors - parameters: - - $ref: '#/components/parameters/nextParam' - responses: - 200: - description: Returns a complete list of vendors, separated in pages. - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedVendorsResponse' - 401: - $ref: '#/components/responses/UnauthorizedError' - - /brands: - get: - tags: - - Catalog - summary: Retrieves brands - description: > - This endpoint is optional. It is used to allow advanced use cases for Banner Ads. Talk to - your Account Manager to understand whether you need to implement this endpoint. - operationId: getBrands - parameters: - - in: query - name: search - schema: - type: string - example: delirium tremens - description: > - The search string provided by the user. In case this parameter is missing or an empty - string is provided, all brands should be returned taking into account the other - parameters. - required: false - - in: query - name: vendorID - schema: - type: string - minLength: 1 - example: '9SiwYqqL8vdG' - description: > - Vendor unique identifier. This identifier is given by the marketplace and allows this - service to match the vendor with the proper brands. - required: false - - $ref: '#/components/parameters/nextParam' - responses: - 200: - description: Returns a complete list of brands, separated in pages. - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedBrandsResponse' - 401: - $ref: '#/components/responses/UnauthorizedError' - -components: - responses: - UnauthorizedError: - description: Credentials are missing or invalid. - - schemas: - GetProductsByIDRequest: - type: array - items: - type: string - minLength: 1 - minItems: 0 - maxItems: 50 - example: - - eyGqR4YQgBJa - - KHqzavLNS25n - - wJLZ4TCNZtEW - - GetProductsByIDResponse: - type: array - items: - $ref: '#/components/schemas/Product' - minItems: 0 - maxItems: 50 - - PaginatedResponse: - type: object - properties: - next: - description: > - Id of the next page. This could be for example a page number (as a string) or a cursor - identifying the next page. This attribute will be passed in the `next` query parameter. - type: string - minLength: 1 - example: asTpl1k746 - - Product: - type: object - description: A Product represents a product listed in a marketplace. - properties: - id: - description: The product ID. - type: string - minLength: 1 - example: eyGqR4YQgBJa - readOnly: true - name: - description: The product name. - type: string - minLength: 1 - example: Delirium Tremens Beer Bottle 330cc x6 - description: - description: The product description. - type: string - minLength: 1 - example: Named as \"Best Beer in the World\" in 2008 at the World Beer Championships in Chicago, Illinois. - vendorID: - description: The vendor ID. - type: string - minLength: 1 - example: 9SiwYqqL8vdG - vendorName: - description: The vendor name. - type: string - minLength: 1 - example: Huyghe Brewery - stock: - description: How many items of this product you have available. If this number is greater than 0, it means you have it in stock and you can fulfill a purchase. - type: integer - format: int32 - minimum: 0 - example: 126 - price: - description: The product price in the minimum currency unit (e.g. cents if applicable). Refer to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) to check how many decimals are used in your currency. - type: integer - format: int32 - minimum: 1 - example: 14900 - imageURL: - description: The product image URL. Its size should be between 250x250 and 600x600 pixels. - type: string - format: uri - example: https://r.btcdn.co/r/eyJzaG9wX2lkIjozMzU4LCJnIjoiMjYweCJ9/1759e16e6314a24/669830-Cerveza_Delirium_Tremens_Botella_330cc_x6.png - categoryID: - description: The category id. - type: string - minLength: 1 - example: ahEDqV5uhjj8 - categoryName: - description: The category name. - type: string - minLength: 1 - example: Beers/Belgian - required: - - id - - name - - ProductsResponse: - type: object - required: - - response - properties: - response: - type: array - items: - $ref: '#/components/schemas/Product' - minItems: 0 - maxItems: 50 - - PaginatedProductsResponse: - allOf: - - $ref: '#/components/schemas/PaginatedResponse' - - $ref: '#/components/schemas/ProductsResponse' - - Category: - type: object - properties: - id: - description: > - The category ID. If there is no ID for categories in the marketplace, this - can be the category name as long as it is unique. - type: string - minLength: 1 - example: ahEDqV5uhjj8 - name: - description: The category name. - type: string - minLength: 1 - example: Beers/Belgian - required: - - id - - name - - CategoriesResponse: - type: object - required: - - response - properties: - response: - type: array - items: - $ref: '#/components/schemas/Category' - minItems: 0 - maxItems: 50 - example: - - id: ahEDqV5uhjj8 - name: Beers/Belgian - - id: cJfoUUzG6GOy - name: Beers/Ales/Amber - - id: oTcnv0fJCRiL - name: Beers/Lagers/Bocks - - id: JspphvZBzV09 - name: Beers/Lagers/Blonde - - PaginatedCategoriesResponse: - allOf: - - $ref: '#/components/schemas/PaginatedResponse' - - $ref: '#/components/schemas/CategoriesResponse' - - Vendor: - type: object - properties: - id: - description: The vendor ID. - type: string - minLength: 1 - example: 9SiwYqqL8vdG - name: - description: The vendor name. - type: string - minLength: 1 - example: Huyghe Brewery - required: - - id - - name - - VendorsResponse: - type: object - required: - - response - properties: - response: - type: array - items: - $ref: '#/components/schemas/Vendor' - minItems: 0 - maxItems: 50 - example: - - id: C0n7J6j0WySR - name: Black Neck Brewery - - id: y7v6kSGGUUFn - name: Brewery Chile SA - - id: vhvg6ioBj5fk - name: Coda Brewery - - id: IMwMGVfSsEpQ - name: Kunstmann Brewery - - id: zo8UXchnFWZu - name: United Brewery - - id: 9SiwYqqL8vdG - name: Huyghe Brewery - - PaginatedVendorsResponse: - allOf: - - $ref: '#/components/schemas/PaginatedResponse' - - $ref: '#/components/schemas/VendorsResponse' - - Brand: - type: object - properties: - id: - description: The brand ID. - type: string - minLength: 1 - example: 9SiwYqqL8vdG - name: - description: The brand name. - type: string - minLength: 1 - example: Pepsi - imageURL: - description: The brand image URL. Its size should be between 250x250 and 600x600 pixels. - type: string - format: uri - required: - - id - - name - - BrandsResponse: - type: object - required: - - response - properties: - response: - type: array - items: - $ref: '#/components/schemas/Brand' - minItems: 0 - maxItems: 50 - example: - - id: bC0n7J6j0WySR - name: Black Neck Brewery - imageURL: https://cdn.marketplace.com/bnb.png - - id: by7v6kSGGUUFn - name: Brewery Chile - imageURL: https://cdn.marketplace.com/bc.png - - PaginatedBrandsResponse: - allOf: - - $ref: '#/components/schemas/PaginatedResponse' - - $ref: '#/components/schemas/BrandsResponse' - - securitySchemes: - BearerAuth: - type: http - scheme: bearer - - parameters: - nextParam: - in: query - name: next - schema: - type: string - minLength: 1 - description: > - The string identifying the requested page. In case this parameter is missing then the first - page should be returned. Note that the specifics about this parameter controlled entirely by - what's returned as `next` in a paginated response and could either be a page number or a - cursor. From 15b8ffce99529c87aba9a974f3413238ee191167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 15:45:20 +1000 Subject: [PATCH 08/32] fix: a few more errrors --- topsort-api-v2.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 4e6d231..db98e51 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -507,15 +507,6 @@ paths: application/json: schema: $ref: '#/components/schemas/PredictionRequest' - examples: - - metrics: - ctr: true - opaqueUserId: u_9ske45 - productIds: - - p_PJbnN - - p_ojng4 - objectType: - - listings required: true responses: '200': @@ -526,14 +517,6 @@ paths: application/json: schema: $ref: '#/components/schemas/PredictionResult' - examples: - objectType: listings - predictions: - - productId: p_PJbnN - ctr: 0.03 - - productId: p_ojng4 - ctr: 0.056 - error: false '400': $ref: '#/components/responses/BadRequest' '401': @@ -967,6 +950,15 @@ components: examples: - p_1234 - p_5678 + examples: + - metrics: + ctr: true + opaqueUserId: u_9ske45 + productIds: + - p_PJbnN + - p_ojng4 + objectType: + - listings required: - metrics - productIds @@ -1295,6 +1287,14 @@ components: description: Conversion Rate prediction. description: | Predicted objects. + examples: + objectType: listings + predictions: + - productId: p_PJbnN + ctr: 0.03 + - productId: p_ojng4 + ctr: 0.056 + error: false required: - objectType - predictions From 48804a2e52b4683fa4f33eb2150a6cda785e87ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Thu, 7 Aug 2025 16:28:32 +1000 Subject: [PATCH 09/32] fix: examples for cvr --- topsort-api-v2.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index db98e51..07fa7b6 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -1270,6 +1270,8 @@ components: enum: - listings - banners + examples: + - listings description: The type of object that was predicted. predictions: type: array @@ -1285,8 +1287,11 @@ components: cvr: type: number description: Conversion Rate prediction. - description: | - Predicted objects. + description: Predicted objects + examples: + - productId: product-123 + ctr: 0.05 + cvr: 0.101 examples: objectType: listings predictions: From b2427530a92e1badf2a1f1ab57716ea86a0ea3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 11:55:29 +1000 Subject: [PATCH 10/32] chore: move occurredAt to a component ..also, fix an issue with resolvedBid reference resolution --- topsort-api-v2.yml | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 07fa7b6..26e28de 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -721,6 +721,12 @@ components: description: Identifies the page examples: - /category/electronics + occurredAt: + type: string + format: date-time + description: A RFC3339 formatted timestamp including UTC offset. + examples: + - 2009-01-01T12:59:59-05:00 OpaqueUserID: type: string description: @@ -1538,10 +1544,7 @@ components: examples: - p_Mfk15 resolvedBidId: - type: string - description: An opaque Topsort ID to be used when this item is interacted with. - examples: - - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= + $ref: '#/components/schemas/ResolvedBidID' title: type: string description: @@ -2024,11 +2027,7 @@ components: placement: $ref: '#/components/schemas/Placement' occurredAt: - type: string - format: date-time - description: RFC3339 formatted timestamp including UTC offset. - examples: - - 2009-01-01T12:59:59-05:00 + $ref: '#/components/schemas/occurredAt' opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: @@ -2085,24 +2084,18 @@ components: additionalProperties: false properties: resolvedBidId: - type: string + $ref: '#/components/schemas/ResolvedBidID' description: If the click is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. - examples: - - WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= entity: $ref: '#/components/schemas/Entity' placement: $ref: '#/components/schemas/Placement' occurredAt: - type: string - format: date-time - description: RFC3339 formatted timestamp including UTC offset. - examples: - - 2009-01-01T12:59:59-05:00 + $ref: '#/components/schemas/occurredAt' opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: @@ -2166,14 +2159,11 @@ components: additionalProperties: false properties: occurredAt: - type: string + $ref: '#/components/schemas/occurredAt' description: RFC3339 formatted timestamp, including UTC offset, of the instant in which the order was placed. Please note that purchases will NOT be attributed to an auction that happened after. - examples: - - 2021-10-12T07:20:50.52Z - format: date-time opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' items: @@ -2257,11 +2247,7 @@ components: page: $ref: '#/components/schemas/Page' occurredAt: - type: string - format: date-time - description: RFC3339 formatted timestamp including UTC offset. - examples: - - 2009-01-01T12:59:59-05:00 + $ref: '#/components/schemas/occurredAt' opaqueUserId: $ref: '#/components/schemas/OpaqueUserID' id: From 30d0fd0ed808be162a87a60f7efccb757391419e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 12:10:53 +1000 Subject: [PATCH 11/32] chore: update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc56aca..ab1a379 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Topsort OpenAPI -Topsort uses the [OpenAPI 3.0.1](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.1.md) specification to [document our APIs](https://docs.topsort.com) and we recommend our clients to use these specifications to generate supported client libraries and server scaffolding. This would provide a consistent and robust developer experience across languages. +Topsort uses the [OpenAPI 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) specification to [document our APIs](https://docs.topsort.com) and we recommend our clients to use these specifications to generate supported client libraries and server scaffolding. This would provide a consistent and robust developer experience across languages. ## Using the OpenAPI generator From 6448cbdceb142a60f58deb695ff2a47754700de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 13:51:16 +1000 Subject: [PATCH 12/32] chore: remove unused file The typo is in a file we no longer use. --- .typos.toml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .typos.toml diff --git a/.typos.toml b/.typos.toml deleted file mode 100644 index 037caa6..0000000 --- a/.typos.toml +++ /dev/null @@ -1,2 +0,0 @@ -[default.extend-identifiers] -bneEmHKG2yUe = "bneEmHKG2yUe" From 3fdc30a091129b91d1e38a6c50b0c34bba3f97ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:13:36 +1000 Subject: [PATCH 13/32] feat: improve linting and formatting stack --- .github/matcher-actionlint.json | 30 +- .github/workflows/lint-vacuum.yml | 24 -- .github/workflows/validate-github-actions.yml | 28 +- .prettierrc | 2 +- .yamllint.yaml | 6 + README.md | 5 + topsort-api-v1.yml | 72 ++-- topsort-api-v2.yml | 386 ++++++++---------- 8 files changed, 269 insertions(+), 284 deletions(-) delete mode 100644 .github/workflows/lint-vacuum.yml create mode 100644 .yamllint.yaml diff --git a/.github/matcher-actionlint.json b/.github/matcher-actionlint.json index 7d39109..4613e16 100644 --- a/.github/matcher-actionlint.json +++ b/.github/matcher-actionlint.json @@ -1,17 +1,17 @@ { - "problemMatcher": [ - { - "owner": "actionlint", - "pattern": [ - { - "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$", - "file": 1, - "line": 2, - "column": 3, - "message": 4, - "code": 5 - } - ] - } - ] + "problemMatcher": [ + { + "owner": "actionlint", + "pattern": [ + { + "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] } diff --git a/.github/workflows/lint-vacuum.yml b/.github/workflows/lint-vacuum.yml deleted file mode 100644 index 134acb8..0000000 --- a/.github/workflows/lint-vacuum.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: OpenAPI - -on: - pull_request: - -permissions: - contents: read - pull-requests: write - -jobs: - vacuum-lint: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Check Formatting - run: npx prettier --check topsort-api-v2.yml - - - name: Validate with Vacuum - uses: pb33f/vacuum-action@v2 - with: - openapi_path: "topsort-api-v2.yml" - github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index 7d2247c..98a0114 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -7,8 +7,7 @@ jobs: name: Actionlint runs-on: ubuntu-24.04 steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - name: Install Actionlint env: version: "1.7.7" @@ -17,3 +16,28 @@ jobs: run: | echo "::add-matcher::.github/matcher-actionlint.json" actionlint -color + + prettier: + name: Prettier + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: npx prettier --check ./*.yml + + vacuum-lint: + name: Vacuum + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: pb33f/vacuum-action@v2 + with: + openapi_path: "topsort-api-v2.yml" + github_token: ${{ secrets.GITHUB_TOKEN }} + + yamllint: + name: yamllint + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v6 + - run: uvx yamllint -f github ./*.yml diff --git a/.prettierrc b/.prettierrc index 0176969..7aaa141 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1 @@ -singleQuote: true +printWidth: 100 diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..a92a3b6 --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,6 @@ +extends: default + +rules: + document-start: disable + line-length: + max: 100 diff --git a/README.md b/README.md index ab1a379..d151510 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Topsort uses the [OpenAPI 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) specification to [document our APIs](https://docs.topsort.com) and we recommend our clients to use these specifications to generate supported client libraries and server scaffolding. This would provide a consistent and robust developer experience across languages. +## Validating the file + +- Use [prettier](https://prettier.io/) to format the documents: `bunx prettier -w` +- Use [yamllint](https://github.com/adrienverge/yamllint) to validate the documents: `uvx yamllint *.yml` + ## Using the OpenAPI generator You can find examples on the official [OpenAPI Generator docs](https://openapi-generator.tech/docs/usage#examples). diff --git a/topsort-api-v1.yml b/topsort-api-v1.yml index 37a845d..2ab53e5 100644 --- a/topsort-api-v1.yml +++ b/topsort-api-v1.yml @@ -8,7 +8,7 @@ info: url: http://www.apache.org/licenses/LICENSE-2.0.html x-logo: url: https://assets.topsort.com/Topsort_logo_icon_dark.svg - backgroundColor: '#fff' + backgroundColor: "#fff" altText: Topsort version: 1.0.1 @@ -91,7 +91,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuctionRequest' + $ref: "#/components/schemas/AuctionRequest" required: true responses: 201: @@ -102,11 +102,11 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Auction' + $ref: "#/components/schemas/Auction" 400: - $ref: '#/components/responses/BadRequest' + $ref: "#/components/responses/BadRequest" 401: - $ref: '#/components/responses/UnauthorizedError' + $ref: "#/components/responses/UnauthorizedError" /events: post: @@ -116,11 +116,11 @@ paths: summary: Report an event operationId: reportEvent requestBody: - description: 'Use the `/events` endpoint to notify Topsort about significant consumer interactions on the e-commerce site: impressions -- product links become visible to the consumer; clicks -- the consumer clicks on a product link; and purchases -- the consumer buys some products.' + description: "Use the `/events` endpoint to notify Topsort about significant consumer interactions on the e-commerce site: impressions -- product links become visible to the consumer; clicks -- the consumer clicks on a product link; and purchases -- the consumer buys some products." content: application/json: schema: - $ref: '#/components/schemas/Event' + $ref: "#/components/schemas/Event" required: true responses: 200: @@ -133,13 +133,13 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/ImpressionsResponse' - - $ref: '#/components/schemas/ClickResponse' - - $ref: '#/components/schemas/PurchaseResponse' + - $ref: "#/components/schemas/ImpressionsResponse" + - $ref: "#/components/schemas/ClickResponse" + - $ref: "#/components/schemas/PurchaseResponse" 401: - $ref: '#/components/responses/UnauthorizedError' + $ref: "#/components/responses/UnauthorizedError" 400: - $ref: '#/components/responses/BadRequest' + $ref: "#/components/responses/BadRequest" components: responses: @@ -150,7 +150,7 @@ components: content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: "#/components/schemas/Error" schemas: AuctionRequest: @@ -160,17 +160,17 @@ components: - products properties: slots: - $ref: '#/components/schemas/Slots' + $ref: "#/components/schemas/Slots" products: type: array description: An array of objects, each describing a product that should participate in the auction. items: - $ref: '#/components/schemas/Product' + $ref: "#/components/schemas/Product" minItems: 1 session: - $ref: '#/components/schemas/Session' + $ref: "#/components/schemas/Session" geoTargeting: - $ref: '#/components/schemas/GeoTargeting' + $ref: "#/components/schemas/GeoTargeting" example: slots: listings: 2 @@ -198,10 +198,9 @@ components: winners: type: array items: - $ref: '#/components/schemas/Winner' - description: - 'Array of winner objects in order from highest to lowest bid. - May be empty if there were no qualifying bids.' + $ref: "#/components/schemas/Winner" + description: "Array of winner objects in order from highest to lowest bid. + May be empty if there were no qualifying bids." GeoTargeting: type: object @@ -320,9 +319,9 @@ components: enum: - Click session: - $ref: '#/components/schemas/Session' + $ref: "#/components/schemas/Session" placement: - $ref: '#/components/schemas/Placement' + $ref: "#/components/schemas/Placement" productId: type: string description: The product that was clicked. @@ -342,7 +341,7 @@ components: type: string format: date-time description: RFC3339 formatted timestamp including UTC offset - example: '2009-01-01T12:59:59-05:00' + example: "2009-01-01T12:59:59-05:00" resolvedBidId: type: string minLength: 1 @@ -373,12 +372,12 @@ components: enum: - Impression session: - $ref: '#/components/schemas/Session' + $ref: "#/components/schemas/Session" impressions: type: array minItems: 1 items: - $ref: '#/components/schemas/Impression' + $ref: "#/components/schemas/Impression" example: - resolvedBidId: WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= id: 234f678-f90c @@ -393,7 +392,7 @@ components: type: string format: date-time description: RFC3339 formatted timestamp including UTC offset - example: '2022-01-23T12:34:56-05:00' + example: "2022-01-23T12:34:56-05:00" Impression: type: object @@ -401,7 +400,7 @@ components: - placement properties: placement: - $ref: '#/components/schemas/Placement' + $ref: "#/components/schemas/Placement" productId: type: string description: The product that was rendered. @@ -437,7 +436,7 @@ components: enum: - Purchase session: - $ref: '#/components/schemas/Session' + $ref: "#/components/schemas/Session" id: type: string description: The marketplace assigned ID for the order. @@ -446,14 +445,14 @@ components: purchasedAt: type: string description: RFC3339 formatted timestamp including UTC offset - example: '2021-10-12T07:20:50.52Z' + example: "2021-10-12T07:20:50.52Z" format: date-time items: type: array description: Items purchased. minItems: 1 items: - $ref: '#/components/schemas/PurchaseItem' + $ref: "#/components/schemas/PurchaseItem" PurchaseItem: type: object @@ -493,9 +492,9 @@ components: Event: oneOf: - - $ref: '#/components/schemas/ImpressionEvent' - - $ref: '#/components/schemas/ClickEvent' - - $ref: '#/components/schemas/PurchaseEvent' + - $ref: "#/components/schemas/ImpressionEvent" + - $ref: "#/components/schemas/ClickEvent" + - $ref: "#/components/schemas/PurchaseEvent" ImpressionResponse: type: object @@ -518,7 +517,7 @@ components: type: array description: The collection of all impressions that were processed correctly. items: - $ref: '#/components/schemas/ImpressionResponse' + $ref: "#/components/schemas/ImpressionResponse" example: impressions: - impressionId: 70ed4d78-34aa-42c7-b6e2-6a670568b6e3 @@ -554,8 +553,7 @@ components: - purchaseId Slots: - description: - 'The Slots object specifies how many auctions winners should be + description: 'The Slots object specifies how many auctions winners should be returned for each promotion type. The promotion types depend on the marketplace configuration. For sponsored listings, use the "listings" key.' diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 26e28de..4344263 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -15,7 +15,7 @@ info: url: http://www.apache.org/licenses/LICENSE-2.0.html x-logo: url: https://assets.topsort.com/Topsort_logo_icon_dark.svg - backgroundColor: '#fff' + backgroundColor: "#fff" altText: Topsort version: 2.0.0 servers: @@ -23,8 +23,7 @@ servers: description: Base API URL tags: - name: Auctions - description: - An auction determines which products should be promoted based on + description: An auction determines which products should be promoted based on the vendors' bids. - name: Events description: > @@ -64,12 +63,12 @@ paths: auctions: type: array items: - $ref: '#/components/schemas/AuctionRequest' + $ref: "#/components/schemas/AuctionRequest" minItems: 1 maxItems: 5 required: true responses: - '201': + "201": description: > The auction results. The list of winners will contain at most `slots` entries per auction. It may contain fewer or no entries at @@ -86,7 +85,7 @@ paths: results: type: array items: - $ref: '#/components/schemas/AuctionResult' + $ref: "#/components/schemas/AuctionResult" minItems: 1 maxItems: 5 required: @@ -125,10 +124,10 @@ paths: - results: - winners: [] error: false - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /v2/auctions/sponsored-brand: post: tags: @@ -148,14 +147,14 @@ paths: auctions: type: array items: - $ref: '#/components/schemas/SponsoredBrandAuctionRequest' + $ref: "#/components/schemas/SponsoredBrandAuctionRequest" minItems: 1 maxItems: 5 required: - auctions required: true responses: - '201': + "201": description: > The auction results. The list of winners will contain at most `winners` entries per auction. It may contain fewer or no entries at @@ -172,22 +171,21 @@ paths: results: type: array items: - $ref: '#/components/schemas/SponsoredBrandAuctionResult' + $ref: "#/components/schemas/SponsoredBrandAuctionResult" minItems: 1 maxItems: 5 required: - results - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /v2/auctions/travel: post: tags: - Auctions summary: Create travel auctions - description: - Use the `/auctions/travel` endpoint to create batch auctions for + description: Use the `/auctions/travel` endpoint to create batch auctions for sponsored travel listings. We support two types of sponsored travel listings, hotels and flights. Each batch of auction requests can be a combination of sponsored hotel and flight listing auctions. Each auction @@ -208,7 +206,7 @@ paths: auctions: type: array items: - $ref: '#/components/schemas/TravelAuctionRequest' + $ref: "#/components/schemas/TravelAuctionRequest" minItems: 1 maxItems: 5 required: @@ -233,11 +231,11 @@ paths: slots: 2 products: - id: L0_SAO-ORL - variationID: '001' + variationID: "001" price: 1500 qualityScore: 0.7 - id: L0_SAO-ORL - variationID: '002' + variationID: "002" price: 2000 travelContext: site: argentina @@ -246,7 +244,7 @@ paths: flightType: one-way required: true responses: - '201': + "201": description: > The auction results. The list of winners will contain at most `winners` entries per auction. It may contain fewer or no entries at @@ -263,7 +261,7 @@ paths: results: type: array items: - $ref: '#/components/schemas/TravelAuctionResult' + $ref: "#/components/schemas/TravelAuctionResult" minItems: 1 maxItems: 5 required: @@ -286,16 +284,16 @@ paths: id: L0_SAO-ORL resolvedBidId: ChAKf-N45Vq3LOTEGcW9VDhKHjADk3_zCXx8db-XZsyiwM2HIjADk4Lr_X0_b9Xw_uKHgyRZKhUKCTHQCTHrrh7 campaignId: 8ab7b29e-1934-4ec9-ad87-60c285bc7f38 - variationID: '002' + variationID: "002" - rank: 2 id: L0_SAO-ORL resolvedBidId: ChAGg-P56Wu4MRUEHdX8VEfLHkBEk4_aEXz9fb-YZtxjwN3IJkBEk5Ms_W2_c8Yx_vZJhzSXKlVLDUJQDUJssl8 campaignId: cb8ed0a7-0ecf-4ffb-a863-022f862649ec - variationID: '001' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + variationID: "001" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /v2/events: post: tags: @@ -331,20 +329,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsRequest' + $ref: "#/components/schemas/EventsRequest" required: true responses: - '204': + "204": description: All events were reported successfully. - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /v2/events/beta/link-users: post: tags: - Events - summary: '[Beta] Report Link Users' + summary: "[Beta] Report Link Users" description: > Use the `/events/beta/link-users` endpoint to report to Topsort linked opaque user IDs. @@ -358,7 +356,7 @@ paths: Contact your sales representative to gain access to this endpoint and start using it. - x-beta: 'true' + x-beta: "true" operationId: linkUsers requestBody: content: @@ -384,17 +382,17 @@ paths: to: user456 required: true responses: - '204': + "204": description: Users account link was reported successfully. - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /toptimize/v1/rank: post: tags: - Toptimize - summary: '[Beta] Rank objects' + summary: "[Beta] Rank objects" operationId: createRanking description: > > ⚠️ **Beta Access Required** @@ -410,7 +408,7 @@ paths: description: > The context information to get the ranking, to rank organic and sponsored products. - x-beta: 'true' + x-beta: "true" content: application/json: schema: @@ -419,7 +417,7 @@ paths: ranking: type: array items: - $ref: '#/components/schemas/RankingRequest' + $ref: "#/components/schemas/RankingRequest" minItems: 1 maxItems: 5 required: @@ -439,7 +437,7 @@ paths: - p_ojng4 required: true responses: - '201': + "201": description: > The ranking results. The list of winners will contain at most `slots` entries per auction. It may contain fewer or no entries at @@ -452,7 +450,7 @@ paths: results: type: array items: - $ref: '#/components/schemas/RankingResult' + $ref: "#/components/schemas/RankingResult" minItems: 1 maxItems: 5 required: @@ -473,15 +471,15 @@ paths: id: p_PJbnN resolvedItemId: WyJlX1BKYm5OIiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0= error: false - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /toptimize/v1/predictions: post: tags: - Toptimize - summary: '[Beta] Add Quality Score' + summary: "[Beta] Add Quality Score" description: > Use the `/predictions` endpoint to get contextual predictions of conversion and relevance metrics, @@ -502,30 +500,30 @@ paths: The context information for the predictions, including which metrics to predict. - x-beta: 'true' + x-beta: "true" content: application/json: schema: - $ref: '#/components/schemas/PredictionRequest' + $ref: "#/components/schemas/PredictionRequest" required: true responses: - '200': + "200": description: > The prediction results. This will provide a numerical value for each combination of metric/product requested on the API call. content: application/json: schema: - $ref: '#/components/schemas/PredictionResult' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + $ref: "#/components/schemas/PredictionResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" /toptimize/v1/retrieval: post: tags: - Toptimize - summary: '[Beta] Retrieve objects' + summary: "[Beta] Retrieve objects" description: > > ⚠️ **Beta Access Required** @@ -548,11 +546,11 @@ paths: description: > The context information for the predictions, including which metrics to predict. - x-beta: 'true' + x-beta: "true" content: application/json: schema: - $ref: '#/components/schemas/RetrievalRequest' + $ref: "#/components/schemas/RetrievalRequest" examples: slots: 5 opaqueUserId: u_9ske45 @@ -564,14 +562,14 @@ paths: - mobile required: true responses: - '200': + "200": description: > The retrieval results. Each retrieved products is accompanied by their relevancy score. content: application/json: schema: - $ref: '#/components/schemas/RetrievalResults' + $ref: "#/components/schemas/RetrievalResults" examples: - objectType: listing objects: @@ -582,10 +580,10 @@ paths: - id: p_ds7ui value: 0.877 error: false - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/UnauthorizedError' + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/UnauthorizedError" components: responses: UnauthorizedError: @@ -595,11 +593,11 @@ components: content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: "#/components/schemas/Error" schemas: Category: oneOf: - - $ref: '#/components/schemas/SingleCategory' + - $ref: "#/components/schemas/SingleCategory" - type: object title: Multiple Categories description: A set of categories for the purpose of running an auction. @@ -623,8 +621,7 @@ components: - c_shoes - type: object title: Category Disjunctions - description: - Multiple disjunctions of categories for the purpose of running an + description: Multiple disjunctions of categories for the purpose of running an auction. required: - disjunctions @@ -637,7 +634,7 @@ components: In order to participate in an auction, a bid product must belong to at least one of the categories of the disjunction provided in the auction request. items: - $ref: '#/components/schemas/CategoryDisjunction' + $ref: "#/components/schemas/CategoryDisjunction" minItems: 1 maxItems: 5 examples: @@ -729,8 +726,7 @@ components: - 2009-01-01T12:59:59-05:00 OpaqueUserID: type: string - description: - The opaque user ID is an anonymized unique identifier that maps to + description: The opaque user ID is an anonymized unique identifier that maps to the original user ID without revealing the original value. This identifier allows Topsort to correlate user activity between auctions and user interactions, independent of the user's logged-in status. For @@ -749,8 +745,7 @@ components: description: The marketplace's ID of the placement where the ad will appear. GeoTargeting: type: object - description: - An object describing geographical information associated with this + description: An object describing geographical information associated with this auction. required: - location @@ -781,22 +776,21 @@ components: type: integer format: int32 minimum: 1 - description: - Specifies the maximum number of auction winners that should be + description: Specifies the maximum number of auction winners that should be returned. category: - $ref: '#/components/schemas/Category' + $ref: "#/components/schemas/Category" searchQuery: type: string description: The search string provided by a user. products: - $ref: '#/components/schemas/Products' + $ref: "#/components/schemas/Products" geoTargeting: - $ref: '#/components/schemas/GeoTargeting' + $ref: "#/components/schemas/GeoTargeting" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" placementId: - $ref: '#/components/schemas/PlacementId' + $ref: "#/components/schemas/PlacementId" required: - type - slots @@ -829,30 +823,28 @@ components: type: integer format: int32 minimum: 1 - description: - Specifies the maximum number of auction winners that should be + description: Specifies the maximum number of auction winners that should be returned. category: - $ref: '#/components/schemas/Category' + $ref: "#/components/schemas/Category" searchQuery: type: string description: The search string provided by a user. device: - $ref: '#/components/schemas/Device' + $ref: "#/components/schemas/Device" geoTargeting: - $ref: '#/components/schemas/GeoTargeting' + $ref: "#/components/schemas/GeoTargeting" slotId: type: string - description: - The ID of the banner placement for which this auction will be run + description: The ID of the banner placement for which this auction will be run for. minLength: 1 products: - $ref: '#/components/schemas/Products' + $ref: "#/components/schemas/Products" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" placementId: - $ref: '#/components/schemas/PlacementId' + $ref: "#/components/schemas/PlacementId" required: - type - slots @@ -866,8 +858,8 @@ components: AuctionRequest: description: Describes the intent of running a single auction. oneOf: - - $ref: '#/components/schemas/SponsoredListingsAuction' - - $ref: '#/components/schemas/BannersAuction' + - $ref: "#/components/schemas/SponsoredListingsAuction" + - $ref: "#/components/schemas/BannersAuction" RankingRequest: type: object description: | @@ -882,28 +874,26 @@ components: type: integer format: int32 minimum: 1 - description: - Specifies the maximum number of ranked objects that should be + description: Specifies the maximum number of ranked objects that should be returned. pageSize: type: integer format: int32 minimum: 1 - description: - Specifies the maximum number of ranked objects per page that should + description: Specifies the maximum number of ranked objects per page that should be returned. page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" category: - $ref: '#/components/schemas/Category' + $ref: "#/components/schemas/Category" device: - $ref: '#/components/schemas/Device' + $ref: "#/components/schemas/Device" geoTargeting: - $ref: '#/components/schemas/GeoTargeting' + $ref: "#/components/schemas/GeoTargeting" products: - $ref: '#/components/schemas/Products' + $ref: "#/components/schemas/Products" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" required: - type - slots @@ -927,8 +917,7 @@ components: properties: metrics: type: object - description: - Metrics to predict, the response will include all the selected + description: Metrics to predict, the response will include all the selected metrics. properties: ctr: @@ -938,9 +927,9 @@ components: type: boolean description: If `true` a Conversion Rate prediction will be made. opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" objectType: type: string description: The type of object that is being reported on the interaction. @@ -948,7 +937,7 @@ components: - listings - banners deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" productIds: type: array items: @@ -982,9 +971,9 @@ components: minimum: 1 maximum: 100 opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" objectType: type: string description: The type of object that needs to be retrieved. @@ -992,7 +981,7 @@ components: - listings - banners deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" seedProductIds: type: array items: @@ -1017,15 +1006,15 @@ components: discriminator: propertyName: resultType mapping: - listings: '#/components/schemas/SponsoredListingsAuctionResult' - banners: '#/components/schemas/BannersAuctionResult' + listings: "#/components/schemas/SponsoredListingsAuctionResult" + banners: "#/components/schemas/BannersAuctionResult" oneOf: - - $ref: '#/components/schemas/SponsoredListingsAuctionResult' - - $ref: '#/components/schemas/BannersAuctionResult' + - $ref: "#/components/schemas/SponsoredListingsAuctionResult" + - $ref: "#/components/schemas/BannersAuctionResult" TravelAuctionResult: oneOf: - - $ref: '#/components/schemas/HotelsAuctionResult' - - $ref: '#/components/schemas/FlightsAuctionResult' + - $ref: "#/components/schemas/HotelsAuctionResult" + - $ref: "#/components/schemas/FlightsAuctionResult" BannersAuctionResult: type: object properties: @@ -1034,7 +1023,7 @@ components: winners: type: array items: - $ref: '#/components/schemas/BannersWinner' + $ref: "#/components/schemas/BannersWinner" description: > Array of winner objects in order from highest to lowest bid. It will be empty if there were no qualifying bids or if there was an @@ -1056,7 +1045,7 @@ components: winners: type: array items: - $ref: '#/components/schemas/SponsoredListingsWinner' + $ref: "#/components/schemas/SponsoredListingsWinner" description: > Array of winner objects in order from highest to lowest bid. It will be empty if there were no qualifying bids or if there was an @@ -1097,13 +1086,12 @@ components: - url id: type: string - description: - The marketplace's ID of the winning entity, depending on the target + description: The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. @@ -1136,13 +1124,12 @@ components: - url id: type: string - description: - The marketplace's ID of the winning entity, depending on the target + description: The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. @@ -1152,10 +1139,10 @@ components: description: The list of available sources for a banner. type: array items: - $ref: '#/components/schemas/AssetSource' + $ref: "#/components/schemas/AssetSource" minItems: 1 HotelsAuctionResult: - $ref: '#/components/schemas/SponsoredListingsAuctionResult' + $ref: "#/components/schemas/SponsoredListingsAuctionResult" FlightsAuctionResult: type: object properties: @@ -1164,7 +1151,7 @@ components: winners: type: array items: - $ref: '#/components/schemas/FlightsWinner' + $ref: "#/components/schemas/FlightsWinner" description: > Array of winner objects in order from highest to lowest bid. It will be empty if there were no qualifying bids or if there was an @@ -1203,13 +1190,12 @@ components: - product id: type: string - description: - The marketplace's ID of the winning flight product, depending on + description: The marketplace's ID of the winning flight product, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' + $ref: "#/components/schemas/ResolvedBidID" campaignId: type: string description: The ID of the campaign that won the auction. @@ -1226,7 +1212,7 @@ components: results: type: array items: - $ref: '#/components/schemas/RankingWinner' + $ref: "#/components/schemas/RankingWinner" description: | Array of ranking objects in order from highest to lowest relevancy. error: @@ -1353,8 +1339,7 @@ components: - banner_asset_001 clickType: type: string - description: - When type is `listing`, signals the specific interaction flavor + description: When type is `listing`, signals the specific interaction flavor with the listing. enum: - product @@ -1432,8 +1417,7 @@ components: type: integer format: int32 minimum: 1 - description: - Specifies the maximum number of auction winners that should be + description: Specifies the maximum number of auction winners that should be returned. placementId: type: string @@ -1445,11 +1429,11 @@ components: id: ne5n2vzri6o92 properties: category: - $ref: '#/components/schemas/SingleCategory' + $ref: "#/components/schemas/SingleCategory" products: - $ref: '#/components/schemas/Products' + $ref: "#/components/schemas/Products" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" x-examples: Example 1: auctions: @@ -1458,15 +1442,15 @@ components: triggers: products: ids: - - '1' - - '8' + - "1" + - "8" SponsoredBrandAuctionResult: type: object properties: winners: type: array items: - $ref: '#/components/schemas/SponsoredBrandWinner' + $ref: "#/components/schemas/SponsoredBrandWinner" description: > Array of winner objects in order from highest to lowest bid. It will be empty if there were no qualifying bids or if there was an @@ -1485,7 +1469,7 @@ components: - winners: - rank: 1 resolvedBidId: ChAGc-G66Wt7LKQEOcW8VBdIEhABjz_zDXx7db-ZYpxiwJ3DGhABjr4Lt_J0_a7Xv_uIfyOXIgUKATEQATDrrg8 - productId: '1' + productId: "1" title: Brand Example Promo 1 assets: - url: https://assets.hosted.topsort.com/5bcccb92e5eaaa73ce9fcc545e944865bf70e9b60e5a048979769282450343c4/example-banner-1.png @@ -1503,7 +1487,7 @@ components: campaignId: 018f3ff3-0d7c-7b75-bf99-629c62c09dc3 - rank: 2 resolvedBidId: ChAGc-G66Wt7LKQEOcW8VBdIEhABk0pue7N5wYmzE04uO_iOGhABjr4Lt_J0_a7Xv_uIfyOXIgUKATgQATDrrg8 - productId: '8' + productId: "8" title: Brand Example Promo 2 assets: - url: https://assets.hosted.topsort.com/c049a46d834ab071cdde63e401d4efcd554e1a124f05c4ba9b3743fed2d43c4b/example-banner-2.jpeg @@ -1538,17 +1522,15 @@ components: minimum: 1 productId: type: string - description: - The marketplace's ID of the winning entity, depending on the target + description: The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' + $ref: "#/components/schemas/ResolvedBidID" title: type: string - description: - An optional title for the sponsored brand selected when creating + description: An optional title for the sponsored brand selected when creating the campaign. vendorId: type: string @@ -1559,7 +1541,7 @@ components: description: Assets used to render the sponsored brand ad. type: array items: - $ref: '#/components/schemas/SponsoredBrandAsset' + $ref: "#/components/schemas/SponsoredBrandAsset" minItems: 1 SponsoredBrandAsset: type: object @@ -1591,8 +1573,8 @@ components: TravelAuctionRequest: description: Describes the intent of running a single auction. oneOf: - - $ref: '#/components/schemas/HotelsAuctionRequest' - - $ref: '#/components/schemas/FlightsAuctionRequest' + - $ref: "#/components/schemas/HotelsAuctionRequest" + - $ref: "#/components/schemas/FlightsAuctionRequest" HotelsAuctionRequest: type: object description: Describes the intent of running a hotel travel auction. @@ -1608,8 +1590,7 @@ components: slots: type: integer format: int32 - description: - Specifies the maximum number of auction winners that should be + description: Specifies the maximum number of auction winners that should be returned. If slots > 40, it is capped at 40. minimum: 1 maximum: 40 @@ -1617,7 +1598,7 @@ components: type: array description: An array of hotels products that should participate in the auction. items: - $ref: '#/components/schemas/HotelsTravelProduct' + $ref: "#/components/schemas/HotelsTravelProduct" category: description: A category for the purpose of running an auction. type: object @@ -1635,7 +1616,7 @@ components: examples: - c_buenos-aires-hotels travelContext: - $ref: '#/components/schemas/HotelsTravelContext' + $ref: "#/components/schemas/HotelsTravelContext" HotelsTravelProduct: type: object required: @@ -1704,7 +1685,7 @@ components: description: Platform e.g. "app", "mobile", "web", ... HotelsTravelContext: allOf: - - $ref: '#/components/schemas/BaseTravelContext' + - $ref: "#/components/schemas/BaseTravelContext" FlightsAuctionRequest: type: object description: Describes the intent of running a flight travel auction. @@ -1720,8 +1701,7 @@ components: slots: type: integer format: int32 - description: - Specifies the maximum number of auction winners that should be + description: Specifies the maximum number of auction winners that should be returned. If slots > 40, it is capped at 40. minimum: 1 maximum: 40 @@ -1729,9 +1709,9 @@ components: type: array description: An array of flight products that should participate in the auction. items: - $ref: '#/components/schemas/FlightsTravelProduct' + $ref: "#/components/schemas/FlightsTravelProduct" travelContext: - $ref: '#/components/schemas/FlightsTravelContext' + $ref: "#/components/schemas/FlightsTravelContext" FlightsTravelProduct: type: object required: @@ -1762,7 +1742,7 @@ components: Values must be between 0 and 1. FlightsTravelContext: allOf: - - $ref: '#/components/schemas/BaseTravelContext' + - $ref: "#/components/schemas/BaseTravelContext" - type: object properties: route: @@ -1810,8 +1790,7 @@ components: docUrl: type: string format: uri - description: - A link to a documentation page providing more information about the + description: A link to a documentation page providing more information about the error. examples: - https://api.docs.topsort.com/reference/errors @@ -1916,25 +1895,25 @@ components: impressions: type: array items: - $ref: '#/components/schemas/Impression' + $ref: "#/components/schemas/Impression" minItems: 1 maxItems: 50 clicks: type: array items: - $ref: '#/components/schemas/Click' + $ref: "#/components/schemas/Click" minItems: 1 maxItems: 50 purchases: type: array items: - $ref: '#/components/schemas/Purchase' + $ref: "#/components/schemas/Purchase" minItems: 1 maxItems: 50 pageviews: type: array items: - $ref: '#/components/schemas/Pageview' + $ref: "#/components/schemas/Pageview" minItems: 1 maxItems: 50 minProperties: 1 @@ -2016,20 +1995,20 @@ components: additionalProperties: false properties: resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' + $ref: "#/components/schemas/ResolvedBidID" description: > If the impression is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. entity: - $ref: '#/components/schemas/Entity' + $ref: "#/components/schemas/Entity" placement: - $ref: '#/components/schemas/Placement' + $ref: "#/components/schemas/Placement" occurredAt: - $ref: '#/components/schemas/occurredAt' + $ref: "#/components/schemas/occurredAt" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" id: type: string description: > @@ -2042,11 +2021,11 @@ components: examples: - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c additionalAttribution: - $ref: '#/components/schemas/Entity' + $ref: "#/components/schemas/Entity" page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" object: - $ref: '#/components/schemas/InteractionObject' + $ref: "#/components/schemas/InteractionObject" externalCampaignId: type: string description: Marketplace provided ID for a campaign @@ -2058,7 +2037,7 @@ components: examples: - my-new-vendor deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" channel: type: string description: Optional. The channel where the event occurred. @@ -2084,20 +2063,19 @@ components: additionalProperties: false properties: resolvedBidId: - $ref: '#/components/schemas/ResolvedBidID' - description: - If the click is over an ad promotion, this is the `resolvedBidId` + $ref: "#/components/schemas/ResolvedBidID" + description: If the click is over an ad promotion, this is the `resolvedBidId` field received from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. entity: - $ref: '#/components/schemas/Entity' + $ref: "#/components/schemas/Entity" placement: - $ref: '#/components/schemas/Placement' + $ref: "#/components/schemas/Placement" occurredAt: - $ref: '#/components/schemas/occurredAt' + $ref: "#/components/schemas/occurredAt" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" id: type: string description: > @@ -2110,15 +2088,14 @@ components: examples: - b39d39ed-ea0e-4059-9d15-4990b39c85a2 additionalAttribution: - $ref: '#/components/schemas/Entity' + $ref: "#/components/schemas/Entity" page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" object: - $ref: '#/components/schemas/InteractionObject' + $ref: "#/components/schemas/InteractionObject" clickType: type: string - description: - For sponsored events only, signals the specific interaction flavor + description: For sponsored events only, signals the specific interaction flavor with the listing. enum: - product @@ -2135,7 +2112,7 @@ components: examples: - my-new-vendor deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" channel: type: string description: Optional. The channel where the event occurred. @@ -2159,19 +2136,18 @@ components: additionalProperties: false properties: occurredAt: - $ref: '#/components/schemas/occurredAt' - description: - RFC3339 formatted timestamp, including UTC offset, of the instant + $ref: "#/components/schemas/occurredAt" + description: RFC3339 formatted timestamp, including UTC offset, of the instant in which the order was placed. Please note that purchases will NOT be attributed to an auction that happened after. opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" items: type: array description: Items purchased. minItems: 1 items: - $ref: '#/components/schemas/PurchaseItem' + $ref: "#/components/schemas/PurchaseItem" id: type: string description: > @@ -2184,7 +2160,7 @@ components: examples: - 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" channel: type: string description: Optional. The channel where the event occurred. @@ -2245,11 +2221,11 @@ components: additionalProperties: false properties: page: - $ref: '#/components/schemas/Page' + $ref: "#/components/schemas/Page" occurredAt: - $ref: '#/components/schemas/occurredAt' + $ref: "#/components/schemas/occurredAt" opaqueUserId: - $ref: '#/components/schemas/OpaqueUserID' + $ref: "#/components/schemas/OpaqueUserID" id: type: string description: > @@ -2262,7 +2238,7 @@ components: examples: - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c deviceType: - $ref: '#/components/schemas/DeviceType' + $ref: "#/components/schemas/DeviceType" channel: type: string description: Optional. The channel where the event occurred. From 2334092df43a1229207dd4fe170f1e805695612a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:24:10 +1000 Subject: [PATCH 14/32] fix: all remaining lint issues except vacuum-related --- .github/workflows/validate-github-actions.yml | 5 +- .prettierrc | 1 - .prettierrc.json | 4 + .yamllint.yaml | 3 +- README.md | 16 +- topsort-api-v1.yml | 109 ++-- topsort-api-v2.yml | 480 ++++++++---------- 7 files changed, 307 insertions(+), 311 deletions(-) delete mode 100644 .prettierrc create mode 100644 .prettierrc.json diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index 98a0114..7817f15 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -11,7 +11,10 @@ jobs: - name: Install Actionlint env: version: "1.7.7" - run: curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin actionlint + run: + curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version + }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin + actionlint - name: Run Actionlint run: | echo "::add-matcher::.github/matcher-actionlint.json" diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 7aaa141..0000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -printWidth: 100 diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..ac50a21 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,4 @@ +{ + "printWidth": 100, + "proseWrap": "always" +} diff --git a/.yamllint.yaml b/.yamllint.yaml index a92a3b6..38c68ba 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -2,5 +2,4 @@ extends: default rules: document-start: disable - line-length: - max: 100 + line-length: disable diff --git a/README.md b/README.md index d151510..7ac25fb 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,20 @@ # Topsort OpenAPI -Topsort uses the [OpenAPI 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) specification to [document our APIs](https://docs.topsort.com) and we recommend our clients to use these specifications to generate supported client libraries and server scaffolding. This would provide a consistent and robust developer experience across languages. +Topsort uses the [OpenAPI 3.1.0][openapi] specification to [document our APIs][docs] and we +recommend our clients to use these specifications to generate supported client libraries and server +scaffolding. This would provide a consistent and robust developer experience across languages. ## Validating the file -- Use [prettier](https://prettier.io/) to format the documents: `bunx prettier -w` -- Use [yamllint](https://github.com/adrienverge/yamllint) to validate the documents: `uvx yamllint *.yml` +- Use [prettier][prettier] to format the documents: `bunx prettier -w` +- Use [yamllint][yamllint] to validate the documents: `uvx yamllint *.yml` ## Using the OpenAPI generator -You can find examples on the official [OpenAPI Generator docs](https://openapi-generator.tech/docs/usage#examples). +You can find examples on the official +[OpenAPI Generator docs](https://openapi-generator.tech/docs/usage#examples). + +[openapi]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md +[docs]: https://docs.topsort.com +[prettier]: https://prettier.io/ +[yamllint]: https://github.com/adrienverge/yamllint diff --git a/topsort-api-v1.yml b/topsort-api-v1.yml index 2ab53e5..483b894 100644 --- a/topsort-api-v1.yml +++ b/topsort-api-v1.yml @@ -85,9 +85,9 @@ paths: operationId: createAuction requestBody: description: > - The information describing what will be auctioned. - Topsort will run an auction for each slot type, for which products' bids will compete against each other. - The products that will participate are included in the request. + The information describing what will be auctioned. Topsort will run an auction for each + slot type, for which products' bids will compete against each other. The products that + will participate are included in the request. content: application/json: schema: @@ -96,9 +96,10 @@ paths: responses: 201: description: - "The auction results. The list of Winner objects will contain at most slots entries. - It may contain fewer or no entries at all if there aren't enough products with usable bids. - Bids become unusable if their campaign budget is exhausted, the bid is disqualified to preserve spend pacing, etc." + "The auction results. The list of Winner objects will contain at most slots entries. It + may contain fewer or no entries at all if there aren't enough products with usable bids. + Bids become unusable if their campaign budget is exhausted, the bid is disqualified to + preserve spend pacing, etc." content: application/json: schema: @@ -116,7 +117,11 @@ paths: summary: Report an event operationId: reportEvent requestBody: - description: "Use the `/events` endpoint to notify Topsort about significant consumer interactions on the e-commerce site: impressions -- product links become visible to the consumer; clicks -- the consumer clicks on a product link; and purchases -- the consumer buys some products." + description: + "Use the `/events` endpoint to notify Topsort about significant consumer interactions on + the e-commerce site: impressions -- product links become visible to the consumer; clicks + -- the consumer clicks on a product link; and purchases -- the consumer buys some + products." content: application/json: schema: @@ -125,10 +130,9 @@ paths: responses: 200: description: - 'An object containing the markeplace ID for the event and the Topsort ID for the same event. - Logging this can facilitate debugging. - The field name for the TopsortID will be "impressionID", "clickId" or "purchaseId" - depending on the event in the request.' + 'An object containing the markeplace ID for the event and the Topsort ID for the same + event. Logging this can facilitate debugging. The field name for the TopsortID will be + "impressionID", "clickId" or "purchaseId" depending on the event in the request.' content: application/json: schema: @@ -163,7 +167,8 @@ components: $ref: "#/components/schemas/Slots" products: type: array - description: An array of objects, each describing a product that should participate in the auction. + description: + An array of objects, each describing a product that should participate in the auction. items: $ref: "#/components/schemas/Product" minItems: 1 @@ -193,14 +198,17 @@ components: properties: auctionId: type: string - description: Topsort assigned ID for the auction. Should be used in reporting impressions, clicks and purchases. + description: + Topsort assigned ID for the auction. Should be used in reporting impressions, + clicks and purchases. example: AKFU78 winners: type: array items: $ref: "#/components/schemas/Winner" - description: "Array of winner objects in order from highest to lowest bid. - May be empty if there were no qualifying bids." + description: + "Array of winner objects in order from highest to lowest bid. May be empty if + there were no qualifying bids." GeoTargeting: type: object @@ -222,17 +230,20 @@ components: rank: type: integer description: > - Where the product's bid ranked in the auction. - One-based, so the product with rank 1 won the auction. - In an auction response, the winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the product with rank 1 won + the auction. In an auction response, the winners array is sorted so rank will match the + entry's index. minimum: 1 productId: type: string - description: The marketplace's ID for the product. It will match the ID for a product in the request's products array. + description: + The marketplace's ID for the product. It will match the ID for a product in the + request's products array. example: pSA0238 winnerType: type: string - description: The type of the winning bid, depending on the campaign. It can be product or vendor. + description: + The type of the winning bid, depending on the campaign. It can be product or vendor. enum: - product - vendor @@ -266,7 +277,9 @@ components: name: Product Session: - description: The Session object allows correlating user activity during a session whether or not they are actually logged in. + description: + The Session object allows correlating user activity during a session whether or not they are + actually logged in. required: - sessionId type: object @@ -275,19 +288,13 @@ components: description: > Long-lived token identifying the customer interacting with the marketplace. - If your users are always logged in you may use a hash of your customer ID. - If your users may interact with your app or site while logged out we recommend generating a random identifier (UUIDv4) on first load and store it on local storage (cookie, local storage, etc) and let it live for at least a year. + If your users are always logged in you may use a hash of your customer ID. If your users + may interact with your app or site while logged out we recommend generating a random + identifier (UUIDv4) on first load and store it on local storage (cookie, local storage, + etc) and let it live for at least a year. type: string minLength: 1 example: ebeaf802-6d0a-41a3-ae59-661887c4f6cb - # consumerId: - # description: > - # Optional ID identifying the user, this field is required in case your marketplace wants to do cross-device attribution. - # - # Instead of sending us the exact same user ID you are storing in your systems we recommend you to send us a hash of the user ID (SHA1, SHA512, etc). - # This field is needed for cross-device attribution. - # type: string - # example: cid_86hkz2p3171joer80pdkltu7n Placement: type: object @@ -306,7 +313,10 @@ components: example: position_1 ClickEvent: - description: ClickEvents are sent to Topsort when the consumer has clicked on an impression. Topsort charges the vendor and pays the marketplace for clicks on impressions in promoted placements on the e-commerce site. + description: + ClickEvents are sent to Topsort when the consumer has clicked on an impression. Topsort + charges the vendor and pays the marketplace for clicks on impressions in promoted placements + on the e-commerce site. type: object required: - eventType @@ -329,7 +339,8 @@ components: example: p_SA0238 auctionId: type: string - description: Required for promoted products. Must be the ID for the auction the product won. + description: + Required for promoted products. Must be the ID for the auction the product won. minLength: 1 example: AKFU78 id: @@ -357,9 +368,11 @@ components: ImpressionEvent: description: > - A product has become visible to the consumer. - In case you cannot send the impression when the product is visible, send us an impression event when the product was rendered in the HTML or if that's also not possible when your API returns the results. - It is important to select the most specific event so that your vendors have more accurate CTR metrics, which allow them to better predict their campaigns. + A product has become visible to the consumer. In case you cannot send the impression when + the product is visible, send us an impression event when the product was rendered in the + HTML or if that's also not possible when your API returns the results. It is important to + select the most specific event so that your vendors have more accurate CTR metrics, which + allow them to better predict their campaigns. type: object required: - eventType @@ -407,7 +420,8 @@ components: example: p_SA0238 auctionId: type: string - description: Required for promoted products. Must be the ID for the auction the product won. + description: + Required for promoted products. Must be the ID for the auction the product won. minLength: 1 example: AKFU78 id: @@ -467,7 +481,9 @@ components: example: p_SA0238 auctionId: type: string - description: If known, the product's auction ID if the consumer clicked on a promoted link before purchasing. + description: + If known, the product's auction ID if the consumer clicked on a promoted link before + purchasing. minLength: 1 example: AKFU78 quantity: @@ -479,7 +495,9 @@ components: unitPrice: type: integer minimum: 1 - description: The price of a single item in minor currency units. For example, in the US (currency code "USD") the unit price is specified in cents. + description: + The price of a single item in minor currency units. For example, in the US (currency + code "USD") the unit price is specified in cents. example: 1295 resolvedBidId: type: string @@ -553,10 +571,10 @@ components: - purchaseId Slots: - description: 'The Slots object specifies how many auctions winners should be - returned for each promotion type. The promotion types depend on - the marketplace configuration. For sponsored listings, use the - "listings" key.' + description: + 'The Slots object specifies how many auctions winners should be returned for each promotion + type. The promotion types depend on the marketplace configuration. For sponsored listings, + use the "listings" key.' type: object properties: listings: @@ -602,8 +620,9 @@ components: message: type: string description: > - Human-readable explanation of or details about the error. - The string for a given error may change over time; code should not parse or dispatch based on particular values for this field. + Human-readable explanation of or details about the error. The string for a given error + may change over time; code should not parse or dispatch based on particular values for + this field. securitySchemes: BearerAuth: diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 4344263..e2aaff5 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -2,8 +2,8 @@ openapi: 3.1.0 info: title: Topsort Endpoints v2 API Reference description: > - In order for a storefront to be able to run auctions in Topsort and - report auction-related events back to Topsort, + In order for a storefront to be able to run auctions in Topsort and report auction-related + events back to Topsort, both the `/v2/auctions` and `/v2/events` endpoints must be integrated. @@ -23,20 +23,20 @@ servers: description: Base API URL tags: - name: Auctions - description: An auction determines which products should be promoted based on - the vendors' bids. + description: An auction determines which products should be promoted based on the vendors' bids. - name: Events description: > - **The specification details, particularly around placement data, - may change in the short term.** + **The specification details, particularly around placement data, may change in the short + term.** - **If this is not acceptable for your integration, please use [Events V1](https://docs.topsort.com/reference/reportevent) as an alternative.** + **If this is not acceptable for your integration, please use [Events + V1](https://docs.topsort.com/reference/reportevent) as an alternative.** Significant consumer interactions on the marketplace app. - name: Toptimize description: > - An out-of-the-box solution for prediction, ranking, retrieval, and - other elements of ad selection. + An out-of-the-box solution for prediction, ranking, retrieval, and other elements of ad + selection. security: - HTTPBearer: [] paths: @@ -46,15 +46,16 @@ paths: - Auctions summary: Create auctions description: > - Use the `/auctions` endpoint to create auctions. Each batch of - auction requests can be a combination of sponsored listing auctions - and banner auctions. Each auction type has a unique body schemas. + Use the `/auctions` endpoint to create auctions. Each batch of auction requests can be a + combination of sponsored listing auctions and banner auctions. Each auction type has a + unique body schemas. operationId: createAuctions requestBody: description: > The information describing what will be auctioned. - Topsort will run an auction for each batched auction request, for which products' bids will compete against each other. + Topsort will run an auction for each batched auction request, for which products' bids + will compete against each other. content: application/json: schema: @@ -70,13 +71,11 @@ paths: responses: "201": description: > - The auction results. The list of winners will contain at most - `slots` entries per auction. It may contain fewer or no entries at - all if there aren't enough products with usable bids, that is, a bid - amount greater than the reserve price and belonging to a campaign - with enough remaining budget. Bids become unusable if campaign - budget is exhausted, the bid is disqualified to preserve spend - pacing, etc. + The auction results. The list of winners will contain at most `slots` entries per + auction. It may contain fewer or no entries at all if there aren't enough products with + usable bids, that is, a bid amount greater than the reserve price and belonging to a + campaign with enough remaining budget. Bids become unusable if campaign budget is + exhausted, the bid is disqualified to preserve spend pacing, etc. content: application/json: schema: @@ -138,7 +137,8 @@ paths: description: > The information describing what will be auctioned. - Topsort will run an auction for each batched auction request, for which products bids will compete against each other. + Topsort will run an auction for each batched auction request, for which products bids will + compete against each other. content: application/json: schema: @@ -156,13 +156,11 @@ paths: responses: "201": description: > - The auction results. The list of winners will contain at most - `winners` entries per auction. It may contain fewer or no entries at - all if there aren't enough products with usable bids, that is, a bid - amount greater than the reserve price and belonging to a campaign - with enough remaining budget. Bids become unusable if campaign - budget is exhausted, the bid is disqualified to preserve spend - pacing, etc. + The auction results. The list of winners will contain at most `winners` entries per + auction. It may contain fewer or no entries at all if there aren't enough products with + usable bids, that is, a bid amount greater than the reserve price and belonging to a + campaign with enough remaining budget. Bids become unusable if campaign budget is + exhausted, the bid is disqualified to preserve spend pacing, etc. content: application/json: schema: @@ -185,19 +183,18 @@ paths: tags: - Auctions summary: Create travel auctions - description: Use the `/auctions/travel` endpoint to create batch auctions for - sponsored travel listings. We support two types of sponsored travel - listings, hotels and flights. Each batch of auction requests can be a - combination of sponsored hotel and flight listing auctions. Each auction + description: + Use the `/auctions/travel` endpoint to create batch auctions for sponsored travel listings. + We support two types of sponsored travel listings, hotels and flights. Each batch of auction + requests can be a combination of sponsored hotel and flight listing auctions. Each auction type has a unique body schemas. operationId: createTravelAuctions requestBody: description: > The information describing what will be auctioned. - Topsort will run an auction for each batched auction request, for which travel products' bids will compete - - against each other. + Topsort will run an auction for each batched auction request, for which travel products' + bids will compete against each other. content: application/json: schema: @@ -246,13 +243,11 @@ paths: responses: "201": description: > - The auction results. The list of winners will contain at most - `winners` entries per auction. It may contain fewer or no entries at - all if there aren't enough products with usable bids, that is, a bid - amount greater than the reserve price and belonging to a campaign - with enough remaining budget. Bids become unusable if campaign - budget is exhausted, the bid is disqualified to preserve spend - pacing, etc. + The auction results. The list of winners will contain at most `winners` entries per + auction. It may contain fewer or no entries at all if there aren't enough products with + usable bids, that is, a bid amount greater than the reserve price and belonging to a + campaign with enough remaining budget. Bids become unusable if campaign budget is + exhausted, the bid is disqualified to preserve spend pacing, etc. content: application/json: schema: @@ -300,8 +295,7 @@ paths: - Events summary: Report events description: > - Use the `/events` endpoint to report user interactions and activity - in on a marketplace: + Use the `/events` endpoint to report user interactions and activity in on a marketplace: - **Impressions** — a user viewed an asset. @@ -312,18 +306,24 @@ paths: - **Pageviews** — a user visited a page. - Interactions require either a `resolvedBidId`, for sponsored events coming from the `/v2/auctions` response, + Interactions require either a `resolvedBidId`, for sponsored events coming from the + `/v2/auctions` response, - or an `entity` that describes the entity that was interacted with, in the case of organic or non-sponsored events. + or an `entity` that describes the entity that was interacted with, in the case of organic or + non-sponsored events. - For analytics purposes, you can use the `placement` field to differentiate different listings or banners. + For analytics purposes, you can use the `placement` field to differentiate different + listings or banners. - For example, on a product page with a carousel of products, you can track impressions and clicks related to the carousel + For example, on a product page with a carousel of products, you can track impressions and + clicks related to the carousel - by including `/carousel` at the end of the `path` field in the `placement` object. This allows you to monitor + by including `/carousel` at the end of the `path` field in the `placement` object. This + allows you to monitor - the performance of carousel products in the [Data Room](https://docs.topsort.com/knowledge-base/analytics/data-room/). + the performance of carousel products in the [Data + Room](https://docs.topsort.com/knowledge-base/analytics/data-room/). operationId: reportEvents requestBody: content: @@ -344,16 +344,11 @@ paths: - Events summary: "[Beta] Report Link Users" description: > - Use the `/events/beta/link-users` endpoint to report to Topsort - linked opaque user IDs. - - - This endpoint allows linking two opaque user IDs for attribution purposes. The `from` field represents the - - original opaque user ID, and the `to` field represents the target opaque user ID to be linked. The request - - will fail if the `from` and `to` opaque user IDs are the same. + Use the `/events/beta/link-users` endpoint to report to Topsort linked opaque user IDs. + This endpoint allows linking two opaque user IDs for attribution purposes. The `from` field + represents the original opaque user ID, and the `to` field represents the target opaque user + ID to be linked. The request will fail if the `from` and `to` opaque user IDs are the same. Contact your sales representative to gain access to this endpoint and start using it. x-beta: "true" @@ -401,13 +396,14 @@ paths: > Contact your sales representative to gain access to this endpoint and start using it. - Use the `/ranking` endpoint to re-rank objects to show on a page. This endpoint can retrieve sponsored + Use the `/ranking` endpoint to re-rank objects to show on a page. This endpoint can retrieve + sponsored - and non-sonsored objects and rank them together, according to an appropriate context and behavior information. + and non-sonsored objects and rank them together, according to an appropriate context and + behavior information. requestBody: description: > - The context information to get the ranking, to rank organic and - sponsored products. + The context information to get the ranking, to rank organic and sponsored products. x-beta: "true" content: application/json: @@ -439,9 +435,9 @@ paths: responses: "201": description: > - The ranking results. The list of winners will contain at most - `slots` entries per auction. It may contain fewer or no entries at - all if there aren't enough products to fill the slots. + The ranking results. The list of winners will contain at most `slots` entries per + auction. It may contain fewer or no entries at all if there aren't enough products to + fill the slots. content: application/json: schema: @@ -481,24 +477,16 @@ paths: - Toptimize summary: "[Beta] Add Quality Score" description: > - Use the `/predictions` endpoint to get contextual predictions of - conversion and relevance metrics, - - which are personalized by user and context. - - - In order to provide predictions, Topsort requires that events are also sent, as a source of - - information. + Use the `/predictions` endpoint to get contextual predictions of conversion and relevance + metrics, which are personalized by user and context.In order to provide predictions, Topsort + requires that events are also sent, as a source of information. operationId: getPredictions requestBody: description: > > ⚠️ **Beta Access Required** - > Contact your sales representative to gain access to this endpoint and start using it. - The context information for the predictions, including which metrics to predict. x-beta: "true" content: @@ -509,8 +497,8 @@ paths: responses: "200": description: > - The prediction results. This will provide a numerical value for - each combination of metric/product requested on the API call. + The prediction results. This will provide a numerical value for each combination of + metric/product requested on the API call. content: application/json: schema: @@ -533,9 +521,11 @@ paths: Use the `/retrieval` endpoint to get recommendations of which products are relevant given a - certain context. Context is provided by user information, plus seed products. This can be used + certain context. Context is provided by user information, plus seed products. This can be + used - to retrieve object to display on a PDP (single seed product) or in a cart (multiple seed products). + to retrieve object to display on a PDP (single seed product) or in a cart (multiple seed + products). In order to provide retrieval, Topsort requires that events are also sent, as a source of @@ -544,8 +534,7 @@ paths: operationId: retrieveObjects requestBody: description: > - The context information for the predictions, including which - metrics to predict. + The context information for the predictions, including which metrics to predict. x-beta: "true" content: application/json: @@ -564,8 +553,7 @@ paths: responses: "200": description: > - The retrieval results. Each retrieved products is accompanied by - their relevancy score. + The retrieval results. Each retrieved products is accompanied by their relevancy score. content: application/json: schema: @@ -607,10 +595,11 @@ components: ids: type: array description: > - An array containing the category IDs of the bids that will - participate in an auction. + An array containing the category IDs of the bids that will participate in an + auction. - In order to participate in an auction, a bid product must belong to **all** of the categories provided in the auction request. + In order to participate in an auction, a bid product must belong to **all** of the + categories provided in the auction request. items: type: string description: A category ID. @@ -621,8 +610,7 @@ components: - c_shoes - type: object title: Category Disjunctions - description: Multiple disjunctions of categories for the purpose of running an - auction. + description: Multiple disjunctions of categories for the purpose of running an auction. required: - disjunctions properties: @@ -632,7 +620,8 @@ components: An array of disjunctions. - In order to participate in an auction, a bid product must belong to at least one of the categories of the disjunction provided in the auction request. + In order to participate in an auction, a bid product must belong to at least one of + the categories of the disjunction provided in the auction request. items: $ref: "#/components/schemas/CategoryDisjunction" minItems: 1 @@ -658,7 +647,8 @@ components: An array of category IDs, describing a category disjunction. - A bid entity must belong to at least one of the categories in the disjunction in order to participate in the auction. + A bid entity must belong to at least one of the categories in the disjunction in order to + participate in the auction. items: type: string description: A category ID. @@ -726,17 +716,16 @@ components: - 2009-01-01T12:59:59-05:00 OpaqueUserID: type: string - description: The opaque user ID is an anonymized unique identifier that maps to - the original user ID without revealing the original value. This - identifier allows Topsort to correlate user activity between auctions - and user interactions, independent of the user's logged-in status. For - apps or sites where users might interact while logged out, we recommend - generating a random identifier (UUIDv7) on the first load, storing it on - local storage (cookie, local storage, etc), and letting it live for at - least a year. Otherwise, if your users are always logged in for - interactions, you may use a hash of your customer ID. Correct purchase - attribution requires long-lived opaque user IDs consistent between - auction and event requests. + description: + The opaque user ID is an anonymized unique identifier that maps to the original user ID + without revealing the original value. This identifier allows Topsort to correlate user + activity between auctions and user interactions, independent of the user's logged-in status. + For apps or sites where users might interact while logged out, we recommend generating a + random identifier (UUIDv7) on the first load, storing it on local storage (cookie, local + storage, etc), and letting it live for at least a year. Otherwise, if your users are always + logged in for interactions, you may use a hash of your customer ID. Correct purchase + attribution requires long-lived opaque user IDs consistent between auction and event + requests. examples: - 71303ce0-de89-496d-8270-6434589615e8 PlacementId: @@ -745,8 +734,7 @@ components: description: The marketplace's ID of the placement where the ad will appear. GeoTargeting: type: object - description: An object describing geographical information associated with this - auction. + description: An object describing geographical information associated with this auction. required: - location properties: @@ -776,8 +764,7 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be - returned. + description: Specifies the maximum number of auction winners that should be returned. category: $ref: "#/components/schemas/Category" searchQuery: @@ -823,8 +810,7 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be - returned. + description: Specifies the maximum number of auction winners that should be returned. category: $ref: "#/components/schemas/Category" searchQuery: @@ -836,8 +822,7 @@ components: $ref: "#/components/schemas/GeoTargeting" slotId: type: string - description: The ID of the banner placement for which this auction will be run - for. + description: The ID of the banner placement for which this auction will be run for. minLength: 1 products: $ref: "#/components/schemas/Products" @@ -874,14 +859,13 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of ranked objects that should be - returned. + description: Specifies the maximum number of ranked objects that should be returned. pageSize: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of ranked objects per page that should - be returned. + description: + Specifies the maximum number of ranked objects per page that should be returned. page: $ref: "#/components/schemas/Page" category: @@ -917,8 +901,7 @@ components: properties: metrics: type: object - description: Metrics to predict, the response will include all the selected - metrics. + description: Metrics to predict, the response will include all the selected metrics. properties: ctr: type: boolean @@ -1025,9 +1008,8 @@ components: items: $ref: "#/components/schemas/BannersWinner" description: > - Array of winner objects in order from highest to lowest bid. It - will be empty if there were no qualifying bids or if there was an - error. + Array of winner objects in order from highest to lowest bid. It will be empty if there + were no qualifying bids or if there was an error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. @@ -1047,9 +1029,8 @@ components: items: $ref: "#/components/schemas/SponsoredListingsWinner" description: > - Array of winner objects in order from highest to lowest bid. It - will be empty if there were no qualifying bids or if there was an - error. + Array of winner objects in order from highest to lowest bid. It will be empty if there + were no qualifying bids or if there was an error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. @@ -1072,9 +1053,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. One-based, so the - product with rank 1 won the auction. In an auction response, the - winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the product with rank 1 won + the auction. In an auction response, the winners array is sorted so rank will match the + entry's index. minimum: 1 type: type: string @@ -1086,8 +1067,8 @@ components: - url id: type: string - description: The marketplace's ID of the winning entity, depending on the target - of the campaign. + description: + The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: @@ -1110,9 +1091,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. One-based, so the - product with rank 1 won the auction. In an auction response, the - winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the product with rank 1 won + the auction. In an auction response, the winners array is sorted so rank will match the + entry's index. minimum: 1 type: type: string @@ -1124,8 +1105,8 @@ components: - url id: type: string - description: The marketplace's ID of the winning entity, depending on the target - of the campaign. + description: + The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: @@ -1153,9 +1134,8 @@ components: items: $ref: "#/components/schemas/FlightsWinner" description: > - Array of winner objects in order from highest to lowest bid. It - will be empty if there were no qualifying bids or if there was an - error. + Array of winner objects in order from highest to lowest bid. It will be empty if there + were no qualifying bids or if there was an error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. @@ -1179,9 +1159,9 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. One-based, so the - product with rank 1 won the auction. In an auction response, the - winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the product with rank 1 won + the auction. In an auction response, the winners array is sorted so rank will match the + entry's index. minimum: 1 type: type: string @@ -1190,8 +1170,9 @@ components: - product id: type: string - description: The marketplace's ID of the winning flight product, depending on - the target of the campaign. + description: + The marketplace's ID of the winning flight product, depending on the target of the + campaign. examples: - p_Mfk15 resolvedBidId: @@ -1339,8 +1320,8 @@ components: - banner_asset_001 clickType: type: string - description: When type is `listing`, signals the specific interaction flavor - with the listing. + description: + When type is `listing`, signals the specific interaction flavor with the listing. enum: - product - like @@ -1353,8 +1334,8 @@ components: type: string format: uri description: > - A vendor provided asset that the marketplace has to use as a - banner. The asset will be served by Topsort's CDN. + A vendor provided asset that the marketplace has to use as a banner. The asset will be + served by Topsort's CDN. required: - url Products: @@ -1365,14 +1346,13 @@ components: ids: type: array description: > - An array of product IDs that should participate in the auction. We - recommend sending no more than 500 products per auction. + An array of product IDs that should participate in the auction. We recommend sending no + more than 500 products per auction. items: type: string description: > - The marketplace's ID of a product which will participate in the - auction. These ID must match those in the catalog integration with - Topsort. + The marketplace's ID of a product which will participate in the auction. These ID must + match those in the catalog integration with Topsort. examples: - p_SA0238 minLength: 1 @@ -1381,10 +1361,11 @@ components: qualityScores: type: array description: > - An array of marketplace defined quality scores, each corresponding - to the product ID with matching array index. + An array of marketplace defined quality scores, each corresponding to the product ID + with matching array index. - If given, these values will be combined with our internal quality scores to provide a score + If given, these values will be combined with our internal quality scores to provide a + score that better represents the relevance of the participating products. @@ -1417,8 +1398,7 @@ components: type: integer format: int32 minimum: 1 - description: Specifies the maximum number of auction winners that should be - returned. + description: Specifies the maximum number of auction winners that should be returned. placementId: type: string x-stoplight: @@ -1452,9 +1432,8 @@ components: items: $ref: "#/components/schemas/SponsoredBrandWinner" description: > - Array of winner objects in order from highest to lowest bid. It - will be empty if there were no qualifying bids or if there was an - error. + Array of winner objects in order from highest to lowest bid. It will be empty if there + were no qualifying bids or if there was an error. error: type: boolean description: A boolean indicating whether this auction was resolved successfully. @@ -1516,22 +1495,22 @@ components: type: integer format: int32 description: > - Where the product's bid ranked in the auction. One-based, so the - product with rank 1 won the auction. In an auction response, the - winners array is sorted so rank will match the entry's index. + Where the product's bid ranked in the auction. One-based, so the product with rank 1 won + the auction. In an auction response, the winners array is sorted so rank will match the + entry's index. minimum: 1 productId: type: string - description: The marketplace's ID of the winning entity, depending on the target - of the campaign. + description: + The marketplace's ID of the winning entity, depending on the target of the campaign. examples: - p_Mfk15 resolvedBidId: $ref: "#/components/schemas/ResolvedBidID" title: type: string - description: An optional title for the sponsored brand selected when creating - the campaign. + description: + An optional title for the sponsored brand selected when creating the campaign. vendorId: type: string description: The ID of the vendor associated with this sponsored brand winner. @@ -1550,8 +1529,8 @@ components: type: string format: uri description: > - A vendor provided asset that the marketplace has to render. The - asset will be served by Topsort's CDN. + A vendor provided asset that the marketplace has to render. The asset will be served by + Topsort's CDN. role: type: string description: The role of the asset. It can be either `logo` or `image`. @@ -1590,8 +1569,9 @@ components: slots: type: integer format: int32 - description: Specifies the maximum number of auction winners that should be - returned. If slots > 40, it is capped at 40. + description: + Specifies the maximum number of auction winners that should be returned. If slots > 40, + it is capped at 40. minimum: 1 maximum: 40 products: @@ -1666,8 +1646,8 @@ components: type: string format: date description: > - RFC3339 formatted date representing the travel end point. Must be - greater than start date. + RFC3339 formatted date representing the travel end point. Must be greater than start + date. examples: - 2025-08-10 travelerType: @@ -1701,8 +1681,9 @@ components: slots: type: integer format: int32 - description: Specifies the maximum number of auction winners that should be - returned. If slots > 40, it is capped at 40. + description: + Specifies the maximum number of auction winners that should be returned. If slots > 40, + it is capped at 40. minimum: 1 maximum: 40 products: @@ -1790,16 +1771,15 @@ components: docUrl: type: string format: uri - description: A link to a documentation page providing more information about the - error. + description: A link to a documentation page providing more information about the error. examples: - https://api.docs.topsort.com/reference/errors message: type: string description: > - Human-readable explanation of or details about the error. The - string for a given error may change over time; code should not parse - or dispatch based on particular values for this field. + Human-readable explanation of or details about the error. The string for a given error + may change over time; code should not parse or dispatch based on particular values for + this field. examples: - could not find the provided resolved bid id Placement: @@ -1811,40 +1791,36 @@ components: path: type: string description: > - URL path of the page triggering the event. - For web apps, this can be obtained in JS using `window.location.pathname`. - For mobile apps, use the deep link for the current view, if available. - Otherwise, encode the view from which the event occurred in your app as a path-like string (e.g. `/root/categories/:categoryId`). + URL path of the page triggering the event. For web apps, this can be obtained in JS + using `window.location.pathname`. For mobile apps, use the deep link for the current + view, if available. Otherwise, encode the view from which the event occurred in your app + as a path-like string (e.g. `/root/categories/:categoryId`). minLength: 1 examples: - /categories/dairy position: type: integer description: > - For components with multiple items (i.e. search results, similar - products, etc), this should indicate the index of a given item - within that list. + For components with multiple items (i.e. search results, similar products, etc), this + should indicate the index of a given item within that list. minimum: 1 page: type: integer description: > - For paginated pages, this should indicate which page number - triggered the event. + For paginated pages, this should indicate which page number triggered the event. minimum: 1 pageSize: type: integer description: > - For paginated pages this should indicate how many items are in each - result page. + For paginated pages this should indicate how many items are in each result page. minimum: 1 examples: - 15 productId: type: string description: > - The ID of the product associated to the page in which this event - occurred, if applicable. This ID must match the ID provided through - the catalog service. + The ID of the product associated to the page in which this event occurred, if + applicable. This ID must match the ID provided through the catalog service. minLength: 1 categoryIds: type: array @@ -1853,25 +1829,22 @@ components: minLength: 1 description: A category ID. description: > - An array of IDs of the categories associated to the page in which - this event occurred, if applicable. These IDs must match the IDs - provided through the catalog service. + An array of IDs of the categories associated to the page in which this event occurred, + if applicable. These IDs must match the IDs provided through the catalog service. minItems: 1 searchQuery: type: string description: > - The search string provided by the user in the page where this event - occurred, if applicable. This search string must match the - searchQuery field that was provided in the auction request (if - provided). + The search string provided by the user in the page where this event occurred, if + applicable. This search string must match the searchQuery field that was provided in the + auction request (if provided). minLength: 1 Entity: type: object description: > - `Entity` is meant for reporting organic events, not sponsored or - promoted products. It refers to the object involved in the organic - interaction. But, in most cases, you won't need to fill in this object. - Be aware that if `resolvedBidId` has any value, `entity` will be + `Entity` is meant for reporting organic events, not sponsored or promoted products. It + refers to the object involved in the organic interaction. But, in most cases, you won't need + to fill in this object. Be aware that if `resolvedBidId` has any value, `entity` will be disregarded. required: - id @@ -1979,14 +1952,12 @@ components: Impression: type: object description: > - An impression means a promotable has become visible to the - consumer. For promoted entities, include the `resolvedBidId` field from - the `/v2/auctions` response. For unpromoted entities, include the - `entity` field to describe what was seen. In case you cannot send an - impression when the product becomes visible, send us an impression event - when the product was rendered in the HTML or, if that's also not - possible, when your API returns the results. It is important to select - the most specific event so that your vendors have more accurate CTR + An impression means a promotable has become visible to the consumer. For promoted entities, + include the `resolvedBidId` field from the `/v2/auctions` response. For unpromoted entities, + include the `entity` field to describe what was seen. In case you cannot send an impression + when the product becomes visible, send us an impression event when the product was rendered + in the HTML or, if that's also not possible, when your API returns the results. It is + important to select the most specific event so that your vendors have more accurate CTR metrics, which will allow them to better predict their campaigns. required: - occurredAt @@ -1997,10 +1968,9 @@ components: resolvedBidId: $ref: "#/components/schemas/ResolvedBidID" description: > - If the impression is over an ad promotion, this is the - `resolvedBidId` field received from the `/auctions` request. In most - situations, especially when reporting a sponsored interaction, - you'll want to fill in this field. + If the impression is over an ad promotion, this is the `resolvedBidId` field received + from the `/auctions` request. In most situations, especially when reporting a sponsored + interaction, you'll want to fill in this field. entity: $ref: "#/components/schemas/Entity" placement: @@ -2012,11 +1982,10 @@ components: id: type: string description: > - The marketplace's unique ID for the impression. This field ensures - the event reporting is idempotent in case there is a network issue - and the request is retried. If there is no impression model on the - marketplace side, generate a unique string that does not change if - the event is resent. + The marketplace's unique ID for the impression. This field ensures the event reporting + is idempotent in case there is a network issue and the request is retried. If there is + no impression model on the marketplace side, generate a unique string that does not + change if the event is resent. minLength: 1 examples: - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c @@ -2049,12 +2018,11 @@ components: - onsite Click: description: > - A click is sent to Topsort when the consumer has clicked on a - promotable. For promoted entities, include the `resolvedBidId` field - from the `/v2/auctions` response. For unpromoted entities, include the - `entity` field to describe what was clicked. Topsort charges the vendor - and pays the marketplace for clicks on ads in promoted placements on the - marketplace app. + A click is sent to Topsort when the consumer has clicked on a promotable. For promoted + entities, include the `resolvedBidId` field from the `/v2/auctions` response. For unpromoted + entities, include the `entity` field to describe what was clicked. Topsort charges the + vendor and pays the marketplace for clicks on ads in promoted placements on the marketplace + app. type: object required: - occurredAt @@ -2064,10 +2032,10 @@ components: properties: resolvedBidId: $ref: "#/components/schemas/ResolvedBidID" - description: If the click is over an ad promotion, this is the `resolvedBidId` - field received from the `/auctions` request. In most situations, - especially when reporting a sponsored interaction, you'll want to - fill in this field. + description: + If the click is over an ad promotion, this is the `resolvedBidId` field received from + the `/auctions` request. In most situations, especially when reporting a sponsored + interaction, you'll want to fill in this field. entity: $ref: "#/components/schemas/Entity" placement: @@ -2079,10 +2047,9 @@ components: id: type: string description: > - The marketplace's unique ID for the click. This field ensures the - event reporting is idempotent in case there is a network issue and - the request is retried. If there is no click model on the - marketplace side, generate a unique string that does not change if + The marketplace's unique ID for the click. This field ensures the event reporting is + idempotent in case there is a network issue and the request is retried. If there is no + click model on the marketplace side, generate a unique string that does not change if the event is resent. minLength: 1 examples: @@ -2095,8 +2062,8 @@ components: $ref: "#/components/schemas/InteractionObject" clickType: type: string - description: For sponsored events only, signals the specific interaction flavor - with the listing. + description: + For sponsored events only, signals the specific interaction flavor with the listing. enum: - product - like @@ -2124,9 +2091,8 @@ components: - onsite Purchase: description: > - A purchase is sent to Topsort once a marketplace customer places an - order. These events are used to measure the effectiveness of an ad - campaign. + A purchase is sent to Topsort once a marketplace customer places an order. These events are + used to measure the effectiveness of an ad campaign. type: object required: - occurredAt @@ -2137,9 +2103,10 @@ components: properties: occurredAt: $ref: "#/components/schemas/occurredAt" - description: RFC3339 formatted timestamp, including UTC offset, of the instant - in which the order was placed. Please note that purchases will NOT - be attributed to an auction that happened after. + description: + RFC3339 formatted timestamp, including UTC offset, of the instant in which the order was + placed. Please note that purchases will NOT be attributed to an auction that happened + after. opaqueUserId: $ref: "#/components/schemas/OpaqueUserID" items: @@ -2151,11 +2118,10 @@ components: id: type: string description: > - The marketplace unique ID for the order. This field ensures the - event reporting is idempotent in case there is a network issue and - the request is retried. If there is no unique ID for orders on the - marketplace side, generate a unique string that does not change if - the event needs to be resent. + The marketplace unique ID for the order. This field ensures the event reporting is + idempotent in case there is a network issue and the request is retried. If there is no + unique ID for orders on the marketplace side, generate a unique string that does not + change if the event needs to be resent. minLength: 1 examples: - 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 @@ -2200,19 +2166,18 @@ components: vendorId: type: string description: > - The vendor ID of the product being purchased. This field is - optional and should be filled in if 1. a product is sold by multiple - vendors, or 2. you want to use it for halo attribution + The vendor ID of the product being purchased. This field is optional and should be + filled in if 1. a product is sold by multiple vendors, or 2. you want to use it for halo + attribution minLength: 1 examples: - v_8fj2D Pageview: type: object description: > - A page view represents the navigation of the user throughout the - page. They are considered organic events. In contrast to clicks or - impressions, which are events within a page, a page view is the - interaction with the full page, which can contain multiple objects. + A page view represents the navigation of the user throughout the page. They are considered + organic events. In contrast to clicks or impressions, which are events within a page, a page + view is the interaction with the full page, which can contain multiple objects. required: - occurredAt - opaqueUserId @@ -2229,10 +2194,9 @@ components: id: type: string description: > - The marketplace's unique ID for the event. This field ensures the - event reporting is idempotent in case there is a network issue and - the request is retried. If there is no pageview model on the - marketplace side, generate a unique string that does not change if + The marketplace's unique ID for the event. This field ensures the event reporting is + idempotent in case there is a network issue and the request is retried. If there is no + pageview model on the marketplace side, generate a unique string that does not change if the event is resent. minLength: 1 examples: From 3bd6a82cb74fdb852da72e8c5fbc7e85d361fdb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:35:18 +1000 Subject: [PATCH 15/32] fix: add redocly lnit --- .github/workflows/validate-github-actions.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index 7817f15..5ebe4aa 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -25,8 +25,9 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: npx prettier --check ./*.yml + - run: npx prettier --check . + # todo, support multiple files vacuum-lint: name: Vacuum runs-on: ubuntu-24.04 @@ -43,4 +44,11 @@ jobs: steps: - uses: actions/checkout@v4 - uses: astral-sh/setup-uv@v6 - - run: uvx yamllint -f github ./*.yml + - run: uvx yamllint -f github topsort-api-*.yml + + redocly: + name: redocly + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: npx redocly lint --format github-actions topsort-api-*.yml From a01cf831ec871a8e3c6098dd3b8bb94dfc2a7786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:38:07 +1000 Subject: [PATCH 16/32] chore: update readme --- .github/workflows/validate-github-actions.yml | 2 +- README.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/validate-github-actions.yml index 5ebe4aa..b43a5cc 100644 --- a/.github/workflows/validate-github-actions.yml +++ b/.github/workflows/validate-github-actions.yml @@ -51,4 +51,4 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: npx redocly lint --format github-actions topsort-api-*.yml + - run: npx @redocly/cli lint --format github-actions topsort-api-*.yml diff --git a/README.md b/README.md index 7ac25fb..a2ea7b5 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ scaffolding. This would provide a consistent and robust developer experience acr - Use [prettier][prettier] to format the documents: `bunx prettier -w` - Use [yamllint][yamllint] to validate the documents: `uvx yamllint *.yml` +- Use [vacuum][vacuum] to validate the openapi standard: `vacuum *.yml` +- Use [redocly][redocly] to further validate the openapi standard: `bunx @redocly/cli lint *.yml` ## Using the OpenAPI generator @@ -18,3 +20,5 @@ You can find examples on the official [docs]: https://docs.topsort.com [prettier]: https://prettier.io/ [yamllint]: https://github.com/adrienverge/yamllint +[vacuum]: https://quobix.com/vacuum/start/ +[redocly]: https://redocly.com/docs/cli/installation From da3a3d62473a90650d72cba3496c43dc826ceecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:40:18 +1000 Subject: [PATCH 17/32] fix: rename workflow --- .github/workflows/{validate-github-actions.yml => lint-tools.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{validate-github-actions.yml => lint-tools.yml} (100%) diff --git a/.github/workflows/validate-github-actions.yml b/.github/workflows/lint-tools.yml similarity index 100% rename from .github/workflows/validate-github-actions.yml rename to .github/workflows/lint-tools.yml From 55009fbcd2d156910d72aed5bdfd41e36c4724c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:41:06 +1000 Subject: [PATCH 18/32] fix: rename jobs --- .github/workflows/lint-tools.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint-tools.yml b/.github/workflows/lint-tools.yml index b43a5cc..28b649c 100644 --- a/.github/workflows/lint-tools.yml +++ b/.github/workflows/lint-tools.yml @@ -39,7 +39,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} yamllint: - name: yamllint + name: YAMLLint runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -47,7 +47,7 @@ jobs: - run: uvx yamllint -f github topsort-api-*.yml redocly: - name: redocly + name: Redocly runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 From 7c2c884e5e5773e146790781b9fe7750d77d58b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:50:29 +1000 Subject: [PATCH 19/32] chore: make event id reusable --- .github/workflows/lint-tools.yml | 7 +++++ .github/workflows/validate-typos.yml | 11 -------- topsort-api-v2.yml | 42 +++++++++------------------- 3 files changed, 20 insertions(+), 40 deletions(-) delete mode 100644 .github/workflows/validate-typos.yml diff --git a/.github/workflows/lint-tools.yml b/.github/workflows/lint-tools.yml index 28b649c..dcb65ad 100644 --- a/.github/workflows/lint-tools.yml +++ b/.github/workflows/lint-tools.yml @@ -52,3 +52,10 @@ jobs: steps: - uses: actions/checkout@v4 - run: npx @redocly/cli lint --format github-actions topsort-api-*.yml + + typos: + name: Check for language typos + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: crate-ci/typos@v1.35.2 diff --git a/.github/workflows/validate-typos.yml b/.github/workflows/validate-typos.yml deleted file mode 100644 index 6deee02..0000000 --- a/.github/workflows/validate-typos.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Typos -on: - pull_request: - -jobs: - typos: - name: Check for language typos - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - uses: crate-ci/typos@v1.29.4 diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index e2aaff5..1b28fd5 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -305,14 +305,12 @@ paths: - **Pageviews** — a user visited a page. - Interactions require either a `resolvedBidId`, for sponsored events coming from the `/v2/auctions` response, or an `entity` that describes the entity that was interacted with, in the case of organic or non-sponsored events. - For analytics purposes, you can use the `placement` field to differentiate different listings or banners. @@ -1980,15 +1978,7 @@ components: opaqueUserId: $ref: "#/components/schemas/OpaqueUserID" id: - type: string - description: > - The marketplace's unique ID for the impression. This field ensures the event reporting - is idempotent in case there is a network issue and the request is retried. If there is - no impression model on the marketplace side, generate a unique string that does not - change if the event is resent. - minLength: 1 - examples: - - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c + $ref: "#/components/schemas/EventIdentifier" additionalAttribution: $ref: "#/components/schemas/Entity" page: @@ -2045,15 +2035,7 @@ components: opaqueUserId: $ref: "#/components/schemas/OpaqueUserID" id: - type: string - description: > - The marketplace's unique ID for the click. This field ensures the event reporting is - idempotent in case there is a network issue and the request is retried. If there is no - click model on the marketplace side, generate a unique string that does not change if - the event is resent. - minLength: 1 - examples: - - b39d39ed-ea0e-4059-9d15-4990b39c85a2 + $ref: "#/components/schemas/EventIdentifier" additionalAttribution: $ref: "#/components/schemas/Entity" page: @@ -2116,15 +2098,7 @@ components: items: $ref: "#/components/schemas/PurchaseItem" id: - type: string - description: > - The marketplace unique ID for the order. This field ensures the event reporting is - idempotent in case there is a network issue and the request is retried. If there is no - unique ID for orders on the marketplace side, generate a unique string that does not - change if the event needs to be resent. - minLength: 1 - examples: - - 0e06c899-b2cd-4e0d-b0de-8aefb4b6d0a0 + $ref: "#/components/schemas/EventIdentifier" deviceType: $ref: "#/components/schemas/DeviceType" channel: @@ -2172,6 +2146,16 @@ components: minLength: 1 examples: - v_8fj2D + EventIdentifier: + type: string + description: > + A unique identifier for the request. This field ensures the event reporting + is idempotent in case there is a network issue and the request is retried. If there is + no impression model on the marketplace side, generate a unique string that does not + change if the event is resent. + minLength: 1 + examples: + - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c Pageview: type: object description: > From 3805aeaea60d7a1dafcb7d10bb189d5d99334364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:51:17 +1000 Subject: [PATCH 20/32] fix: lint --- topsort-api-v2.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 1b28fd5..52f4811 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -2149,10 +2149,9 @@ components: EventIdentifier: type: string description: > - A unique identifier for the request. This field ensures the event reporting - is idempotent in case there is a network issue and the request is retried. If there is - no impression model on the marketplace side, generate a unique string that does not - change if the event is resent. + A unique identifier for the request. This field ensures the event reporting is idempotent in + case there is a network issue and the request is retried. If there is no impression model on + the marketplace side, generate a unique string that does not change if the event is resent. minLength: 1 examples: - eb874c98-bf4d-40a9-ae6d-fcf4cecb535c From 4a83a0e815b4e65338f28427f7cf147b56234f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:52:30 +1000 Subject: [PATCH 21/32] fix: typos --- topsort-api-v1.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/topsort-api-v1.yml b/topsort-api-v1.yml index 483b894..0048735 100644 --- a/topsort-api-v1.yml +++ b/topsort-api-v1.yml @@ -130,9 +130,9 @@ paths: responses: 200: description: - 'An object containing the markeplace ID for the event and the Topsort ID for the same + An object containing the marketplace ID for the event and the Topsort ID for the same event. Logging this can facilitate debugging. The field name for the TopsortID will be - "impressionID", "clickId" or "purchaseId" depending on the event in the request.' + "impressionID", "clickId" or "purchaseId" depending on the event in the request. content: application/json: schema: From 3cb6c138654219bdc22cb63c6009a46cf3b9d96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 14:55:01 +1000 Subject: [PATCH 22/32] chore(docs): make a point about where our full openapi documeent lives --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a2ea7b5..5869252 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Topsort uses the [OpenAPI 3.1.0][openapi] specification to [document our APIs][d recommend our clients to use these specifications to generate supported client libraries and server scaffolding. This would provide a consistent and robust developer experience across languages. +You can additionally consume the entire Topsort OpenAPI spec available [here][openapi-ts]. + ## Validating the file - Use [prettier][prettier] to format the documents: `bunx prettier -w` @@ -18,6 +20,7 @@ You can find examples on the official [openapi]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md [docs]: https://docs.topsort.com +[openapi-ts]: https://docs.topsort.com/openapi.json [prettier]: https://prettier.io/ [yamllint]: https://github.com/adrienverge/yamllint [vacuum]: https://quobix.com/vacuum/start/ From 851d9211e138871b6c526436febee2ca21375964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:02:58 +1000 Subject: [PATCH 23/32] chore: switch to vacuum cli --- topsort-api-v1.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/topsort-api-v1.yml b/topsort-api-v1.yml index 0048735..c29fa12 100644 --- a/topsort-api-v1.yml +++ b/topsort-api-v1.yml @@ -1,6 +1,7 @@ openapi: 3.0.1 info: title: Topsort Endpoints v1 API Reference + description: The OpenAPI specifciation for Topsort v1 endpoints contact: email: wicha@topsort.com license: From b9dcac425b20b88a3e36e91ad7b2718884c3c657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:03:51 +1000 Subject: [PATCH 24/32] fix: add missing changes --- .github/workflows/lint-tools.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/lint-tools.yml b/.github/workflows/lint-tools.yml index dcb65ad..869dc06 100644 --- a/.github/workflows/lint-tools.yml +++ b/.github/workflows/lint-tools.yml @@ -15,8 +15,7 @@ jobs: curl -Ls "https://github.com/rhysd/actionlint/releases/download/v${{ env.version }}/actionlint_${{ env.version }}_linux_amd64.tar.gz" | sudo tar -x -z -C /usr/local/bin actionlint - - name: Run Actionlint - run: | + - run: | echo "::add-matcher::.github/matcher-actionlint.json" actionlint -color @@ -27,16 +26,19 @@ jobs: - uses: actions/checkout@v4 - run: npx prettier --check . - # todo, support multiple files - vacuum-lint: + vacuum: name: Vacuum runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: pb33f/vacuum-action@v2 - with: - openapi_path: "topsort-api-v2.yml" - github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Install Vacuum + env: + version: 0.17.8 + run: + curl -Ls "https://github.com/daveshanley/vacuum/releases/download/v${{ env.version + }}/vacuum_${{ env.version }}_linux_x86_64.tar.gz" | sudo tar -x -z -C /usr/local/bin + vacuum + - run: vacuum lint -d -e -b *.yml yamllint: name: YAMLLint From 3d85c03a353657b2eb5aa1ae60bd5738fa918706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:05:15 +1000 Subject: [PATCH 25/32] fix: actionlint --- .github/workflows/lint-tools.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-tools.yml b/.github/workflows/lint-tools.yml index 869dc06..39130fe 100644 --- a/.github/workflows/lint-tools.yml +++ b/.github/workflows/lint-tools.yml @@ -38,7 +38,7 @@ jobs: curl -Ls "https://github.com/daveshanley/vacuum/releases/download/v${{ env.version }}/vacuum_${{ env.version }}_linux_x86_64.tar.gz" | sudo tar -x -z -C /usr/local/bin vacuum - - run: vacuum lint -d -e -b *.yml + - run: vacuum lint -d -e -b ./*.yml yamllint: name: YAMLLint From bf1ce9b2710c9f169e176dfa0b1d0c053bea64bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:12:56 +1000 Subject: [PATCH 26/32] chore: add typos to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5869252..e5004b3 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ You can additionally consume the entire Topsort OpenAPI spec available [here][op - Use [yamllint][yamllint] to validate the documents: `uvx yamllint *.yml` - Use [vacuum][vacuum] to validate the openapi standard: `vacuum *.yml` - Use [redocly][redocly] to further validate the openapi standard: `bunx @redocly/cli lint *.yml` +- Use [typos][typos] to fix language typos: `typos .` ## Using the OpenAPI generator @@ -25,3 +26,4 @@ You can find examples on the official [yamllint]: https://github.com/adrienverge/yamllint [vacuum]: https://quobix.com/vacuum/start/ [redocly]: https://redocly.com/docs/cli/installation +[typos]: https://github.com/crate-ci/typos From a7c5c9eb8420a00ec2b3830f602c31f7653103fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:14:58 +1000 Subject: [PATCH 27/32] chore(docs): improve openapi link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e5004b3..a0c7f41 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ You can additionally consume the entire Topsort OpenAPI spec available [here][op You can find examples on the official [OpenAPI Generator docs](https://openapi-generator.tech/docs/usage#examples). -[openapi]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md +[openapi]: https://spec.openapis.org/oas/v3.1.0.html [docs]: https://docs.topsort.com [openapi-ts]: https://docs.topsort.com/openapi.json [prettier]: https://prettier.io/ From c891ae747ffc7bbd378b8f83b55effc673ddcdbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:19:41 +1000 Subject: [PATCH 28/32] fix: example response is an array --- topsort-api-v2.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 52f4811..a764154 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -1264,13 +1264,14 @@ components: ctr: 0.05 cvr: 0.101 examples: - objectType: listings - predictions: - - productId: p_PJbnN - ctr: 0.03 - - productId: p_ojng4 - ctr: 0.056 - error: false + - objectType: listings + predictions: + - productId: p_PJbnN + ctr: 0.03 + cvr: 0.06 + - productId: p_ojng4 + ctr: 0.056 + cvr: 0.091 required: - objectType - predictions From 7066f0d5201e11d6beb9f5ad0c0ec167408ee3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:24:37 +1000 Subject: [PATCH 29/32] fix: last remaining issues --- topsort-api-v2.yml | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index a764154..cb34889 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -538,15 +538,6 @@ paths: application/json: schema: $ref: "#/components/schemas/RetrievalRequest" - examples: - slots: 5 - opaqueUserId: u_9ske45 - seedProductIds: - - p_PJbnN - - p_ojng4 - mode: all - deviceType: - - mobile required: true responses: "200": @@ -556,16 +547,6 @@ paths: application/json: schema: $ref: "#/components/schemas/RetrievalResults" - examples: - - objectType: listing - objects: - - id: p_xh90s - value: 0.978 - - id: p_12lp0 - value: 0.953 - - id: p_ds7ui - value: 0.877 - error: false "400": $ref: "#/components/responses/BadRequest" "401": @@ -978,6 +959,15 @@ components: - complement - similar default: all + examples: + - slots: 5 + opaqueUserId: u_9ske45 + seedProductIds: + - p_PJbnN + - p_ojng4 + mode: all + deviceType: + - mobile required: - slots - seedProductIds @@ -1295,8 +1285,17 @@ components: score: type: number description: Relevance score for the retrieved products. - description: | - Retrieved objects. + description: Retrieved objects. + examples: + - objectType: listing + objects: + - id: p_xh90s + value: 0.978 + - id: p_12lp0 + value: 0.953 + - id: p_ds7ui + value: 0.877 + error: false required: - objectType - objects From 51f621c2115249a1fd9d3882ff30d0ae3373f60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Fri, 8 Aug 2025 15:26:50 +1000 Subject: [PATCH 30/32] chroe: ignore v1 vacuum lint for now --- .github/workflows/lint-tools.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-tools.yml b/.github/workflows/lint-tools.yml index 39130fe..43f0d34 100644 --- a/.github/workflows/lint-tools.yml +++ b/.github/workflows/lint-tools.yml @@ -38,7 +38,7 @@ jobs: curl -Ls "https://github.com/daveshanley/vacuum/releases/download/v${{ env.version }}/vacuum_${{ env.version }}_linux_x86_64.tar.gz" | sudo tar -x -z -C /usr/local/bin vacuum - - run: vacuum lint -d -e -b ./*.yml + - run: vacuum lint -d -e -b ./topsort-api-v2.yml yamllint: name: YAMLLint From 524c60d2ef9589d3b4679c98a48566bef7e95b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Mon, 11 Aug 2025 13:29:23 +1000 Subject: [PATCH 31/32] chore: rename core schemas These also conflicts with central services --- topsort-api-v2.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index cb34889..32eb338 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -562,7 +562,7 @@ components: schema: $ref: "#/components/schemas/Error" schemas: - Category: + AuctionCategory: oneOf: - $ref: "#/components/schemas/SingleCategory" - type: object @@ -745,7 +745,7 @@ components: minimum: 1 description: Specifies the maximum number of auction winners that should be returned. category: - $ref: "#/components/schemas/Category" + $ref: "#/components/schemas/AuctionCategory" searchQuery: type: string description: The search string provided by a user. @@ -791,7 +791,7 @@ components: minimum: 1 description: Specifies the maximum number of auction winners that should be returned. category: - $ref: "#/components/schemas/Category" + $ref: "#/components/schemas/AuctionCategory" searchQuery: type: string description: The search string provided by a user. @@ -848,7 +848,7 @@ components: page: $ref: "#/components/schemas/Page" category: - $ref: "#/components/schemas/Category" + $ref: "#/components/schemas/AuctionCategory" device: $ref: "#/components/schemas/Device" geoTargeting: @@ -1837,7 +1837,7 @@ components: applicable. This search string must match the searchQuery field that was provided in the auction request (if provided). minLength: 1 - Entity: + EventEntity: type: object description: > `Entity` is meant for reporting organic events, not sponsored or promoted products. It @@ -1970,7 +1970,7 @@ components: from the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. entity: - $ref: "#/components/schemas/Entity" + $ref: "#/components/schemas/EventEntity" placement: $ref: "#/components/schemas/Placement" occurredAt: @@ -1980,7 +1980,7 @@ components: id: $ref: "#/components/schemas/EventIdentifier" additionalAttribution: - $ref: "#/components/schemas/Entity" + $ref: "#/components/schemas/EventEntity" page: $ref: "#/components/schemas/Page" object: @@ -2027,7 +2027,7 @@ components: the `/auctions` request. In most situations, especially when reporting a sponsored interaction, you'll want to fill in this field. entity: - $ref: "#/components/schemas/Entity" + $ref: "#/components/schemas/EventEntity" placement: $ref: "#/components/schemas/Placement" occurredAt: @@ -2037,7 +2037,7 @@ components: id: $ref: "#/components/schemas/EventIdentifier" additionalAttribution: - $ref: "#/components/schemas/Entity" + $ref: "#/components/schemas/EventEntity" page: $ref: "#/components/schemas/Page" object: From 0f57a9a5041f10666fec0068094b09390b9af9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bergstr=C3=B6m?= Date: Mon, 11 Aug 2025 14:57:04 +1000 Subject: [PATCH 32/32] fix: make bearer scheme identical to central services to avoid conflict --- topsort-api-v2.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/topsort-api-v2.yml b/topsort-api-v2.yml index 32eb338..13e5f23 100644 --- a/topsort-api-v2.yml +++ b/topsort-api-v2.yml @@ -2197,5 +2197,6 @@ components: - onsite securitySchemes: HTTPBearer: - type: http + description: A valid API key generated in Topsort's UI. scheme: bearer + type: http