openapi: 3.2.0 info: title: Piknik.Spot Marketplace API description: Piknik.Spot API with OAuth2 authentication, Model Context Protocol (MCP) support, and Agent-to-Agent (A2A) capabilities for AI-powered local food system interactions. version: 1.0.0 contact: name: Piknik.Spot API Support url: https://piknik.spot email: info@piknik.spot license: name: Proprietary url: https://piknik.spot/terms servers: - url: https://piknik.spot/api description: Production Server - url: http://localhost:3000/api description: Development Server tags: - name: Marketplace paths: /listings/{id}/accept: post: summary: POST /api/listings/[id]/accept tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: postListingsByIdAccept x-operation-id-source: derived /listings/{id}/confirm-acceptance: post: summary: POST /api/listings/[id]/confirm-acceptance tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: postListingsByIdConfirmAcceptance x-operation-id-source: derived /listings/{id}/confirm-direct-pickup: post: summary: POST /api/listings/[id]/confirm-direct-pickup tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: postListingsByIdConfirmDirectPickup x-operation-id-source: derived /listings/{id}/decline: post: summary: POST /api/listings/[id]/decline tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: postListingsByIdDecline x-operation-id-source: derived /listings/{id}/decline-acceptance: post: summary: POST /api/listings/[id]/decline-acceptance tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: postListingsByIdDeclineAcceptance x-operation-id-source: derived /listings/{id}/fulfill: post: summary: Mark listing as fulfilled tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: postListingsByIdFulfill x-operation-id-source: derived /listings/{id}/reactivate: post: summary: POST /api/listings/[id]/reactivate tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: postListingsByIdReactivate x-operation-id-source: derived /listings/{id}: get: summary: Get single listing tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: getListingsById x-operation-id-source: derived put: summary: Get single listing tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: putListingsById x-operation-id-source: derived delete: summary: Get single listing tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: deleteListingsById x-operation-id-source: derived /listings/{id}/view: post: summary: POST /listings/{id}/view description: Endpoint for /listings/{id}/view tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: postListingsByIdView x-operation-id-source: derived /listings/my: get: summary: Get current user's listings tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: status in: query schema: type: string description: status parameter operationId: getListingsMy x-operation-id-source: derived /listings: get: summary: Browse Marketplace Listings description: Search and browse marketplace listings with location filtering, search terms, and association filters. tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] parameters: - name: listingType in: query schema: type: boolean description: Type of listing - name: lat in: query schema: type: number format: double description: Latitude coordinate - name: lng in: query schema: type: number format: double description: Longitude coordinate - name: mine in: query schema: type: boolean description: Filter to only user's own items - name: q in: query schema: type: string description: Search query string - name: search in: query schema: type: string description: Search query string - name: maxRadius in: query schema: type: integer description: maxRadius parameter - name: limit in: query schema: type: integer description: Maximum number of results - name: offset in: query schema: type: integer description: Pagination offset - name: participantId in: query schema: type: string description: Participant identifier operationId: getListings x-operation-id-source: derived post: summary: Create Marketplace Listing description: Create a new marketplace listing for buying, selling, or offering services. Requires participant_id from /api/v2/participants/my-businesses. tags: - Marketplace responses: {} security: - bearerAuth: [] - cookieAuth: [] parameters: - name: listingType in: query schema: type: boolean description: Type of listing - name: lat in: query schema: type: number format: double description: Latitude coordinate - name: lng in: query schema: type: number format: double description: Longitude coordinate - name: mine in: query schema: type: boolean description: Filter to only user's own items - name: q in: query schema: type: string description: Search query string - name: search in: query schema: type: string description: Search query string - name: maxRadius in: query schema: type: integer description: maxRadius parameter - name: limit in: query schema: type: integer description: Maximum number of results - name: offset in: query schema: type: integer description: Pagination offset - name: participantId in: query schema: type: string description: Participant identifier requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateListingRequest' operationId: postListings x-operation-id-source: derived /marketplace/contact: post: summary: POST /marketplace/contact description: Endpoint for /marketplace/contact tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: - bearerAuth: [] - cookieAuth: [] requestBody: required: true content: application/json: schema: type: object operationId: postMarketplaceContact x-operation-id-source: derived /widget/listings/{id}/email-pdfs: post: summary: POST /widget/listings/{id}/email-pdfs description: Endpoint for /widget/listings/{id}/email-pdfs tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: postWidgetListingsByIdEmailPdfs x-operation-id-source: derived /widget/listings/{id}: patch: summary: PATCH /widget/listings/{id} description: Endpoint for /widget/listings/{id} tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: [] parameters: - name: id in: path required: true schema: type: string description: id identifier requestBody: required: true content: application/json: schema: type: object operationId: patchWidgetListingsById x-operation-id-source: derived delete: summary: DELETE /widget/listings/{id} description: Endpoint for /widget/listings/{id} tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: [] parameters: - name: id in: path required: true schema: type: string description: id identifier operationId: deleteWidgetListingsById x-operation-id-source: derived /widget/listings: get: summary: GET /widget/listings description: Endpoint for /widget/listings tags: - Marketplace responses: '200': description: Success content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: [] operationId: getWidgetListings x-operation-id-source: derived post: summary: POST /widget/listings description: Endpoint for /widget/listings tags: - Marketplace responses: '201': description: Created successfully content: application/json: schema: type: object '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' security: [] requestBody: required: true content: application/json: schema: type: object operationId: postWidgetListings x-operation-id-source: derived components: schemas: CreateListingRequest: type: object required: - participant_id - listing_type - title - description - contact_method - end_date properties: participant_id: type: string description: ID of the business creating the listing (get from /api/v2/participants/my-businesses) listing_type: type: string enum: - wanted_to_sell - wanted_to_buy - service_offering title: type: string maxLength: 200 description: type: string quantity: type: - string - 'null' contact_method: type: string enum: - email - phone - message radius_km: type: number default: 50 end_date: type: string format: date description: 'ISO date format: YYYY-MM-DD' wanted_in_return: type: - string - 'null' association_ids: type: array items: type: string Error: type: object properties: error: type: string description: Error message error_description: type: string description: Detailed error description securitySchemes: cookieAuth: type: apiKey in: cookie name: next-auth.session-token description: Session-based authentication for web browsers oauth2: type: oauth2 description: OAuth 2.0 authentication for external applications and AI agents flows: authorizationCode: authorizationUrl: https://piknik.spot/api/oauth/authorize tokenUrl: https://piknik.spot/api/oauth/token refreshUrl: https://piknik.spot/api/oauth/token scopes: marketplace:write: Create and manage marketplace listings events:write: Create and manage community events read:profile: Read user profile information write:profile: Update user profile information bearerAuth: type: http scheme: bearer bearerFormat: JWT description: 'OAuth2 access token (JWT). Include in Authorization header as: Bearer {token}'