openapi: 3.1.0
info:
  title: Destinations API
  description: Title
  version: 'v1'
servers:
  - url: https://api.loopreturns.com/api/2026-10
    description: 2026-10 (Stable)
  - url: https://api.loopreturns.com/api/2026-07
    description: 2026-07
  - url: https://api.loopreturns.com/api/unstable
    description: Unstable (Preview)
tags:
  - name: Destinations
paths:
  /destinations:
    get:
      summary: Get All Destinations
      operationId: getAllDestinations
      description: |
        Retrieve all destinations.

        ### Required API key scope
        - Destinations (Read)
      tags:
        - Destinations
      security:
        - api_key: []
      responses:
        "200":
          description: "Success"
          content:
            application/json:
              schema:
                type: object
                properties:
                  destinations:
                    type: array
                    items:
                      $ref: '#/components/schemas/Destination'
        "401":
          description: "Unauthorized"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "500":
          description: "One or more destinations do not have an address."
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorResponse'
    post:
      summary: Create Destination
      description: |
        Create a destination.

        ### Required API key scope
        - Destinations (Write)
      operationId: createDestination
      tags:
        - Destinations
      security:
        - api_key: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateDestinationRequest'
      responses:
        "200":
          description: "Success"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Destination'
        "401":
          description: "Unauthorized"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "422":
          description: 'Unprocessable'
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/UnprocessableResponse'
                  - $ref: '#/components/schemas/DestinationLimitExceeded'
  /destinations/{id}:
    get:
      summary: Get Destination Details
      operationId: getDestination
      description: |
        Get details for a single destination.

        ### Required API key scope
        - Destinations (Read)
      tags:
        - Destinations
      security:
        - api_key: []
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
          example: 12345
          description: The destination's unique identifier.
      responses:
        "200":
          description: "Success"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Destination'
        "400":
          description: 'Invalid destination id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResponse'
        "401":
          description: "Unauthorized"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "404":
          description: 'Destination not found'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundResponse'
    put:
      summary: Update Destination
      description: |
        Update a destination.
        ### Required API key scope
        - Destinations (Write)
      operationId: updateDestination
      tags:
        - Destinations
      security:
        - api_key: []
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
          example: 12345
          description: The destination's unique identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateDestinationRequest'
      responses:
        "200":
          description: "Success"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Destination'
        "401":
          description: "Unauthorized"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "404":
          description: "Destination not found"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundResponse'
        "422":
          description: 'Unprocessable'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableResponse'
    delete:
      summary: Delete Destination
      description: |
        Delete a destination.

        ### Required API key scope
        - Destinations (Write)
      operationId: deleteDestination
      tags:
        - Destinations
      security:
        - api_key: []
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
          example: 12345
          description: The destination's unique identifier.
      responses:
        "204":
          description: "No Content"
        "404":
          description: "Destination not found"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundResponse'
        "500":
          description: "Error in deleting the destination"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorResponse'
components:
  schemas:
    Destination:
      type: object
      description: A physical location such as a warehouse or donation center to which returns are shipped.
      properties:
        id:
          type: integer
          example: 1
          description: The destination's unique identifier.
        type:
          type: string
          enum:
            - warehouse
            - donate
          example: warehouse
          description: The type of location represented by the destination.
        name:
          type: string
          example: Example Destination
          description: The destination's name.
        enabled:
          type: boolean
          example: true
          description: Whether the destination is enabled as a return destination.
        provider_location_id:
          type:
            - integer
            - "null"
          example: 42424242
          description: |
            The numeric location identifier from the commerce platform (for example Shopify) when a
            location is linked to this destination in Loop. `null` when no location is linked. The
            linked location's `source` field indicates which provider the ID belongs to.
        address:
          $ref: '#/components/schemas/Address'
    Address:
      type: object
      description: The destination's address.
      properties:
        name:
          type: [string, "null"]
          example: Main Warehouse
          description: The name associated with the address.
        company:
          type: [string, "null"]
          example: Universal Exports
          description: The company residing at the address.
        address1:
          type: string
          example: 123 Main St
          description: The street address of the destination.
        address2:
          type: [string, "null"]
          example: Unit 456
          description: The secondary address details of the destination.
        city:
          type: string
          example: Columbus
        state:
          type: [string, "null"]
          example: Ohio
        zip:
          type: [string, "null"]
          example: '43210'
        country:
          type: string
          example: 'United States'
        country_code:
          type: string
          example: 'US'
    CreateDestinationRequest:
      type: object
      required:
        - name
        - type
        - address
      properties:
        name:
          type: string
          maxLength: 191
          example: Example Destination
          description: The destination's name.
        type:
          type: string
          enum:
            - warehouse
            - donate
          example: warehouse
          description: The type of location represented by the destination.
        enabled:
          type: boolean
          example: true
          description: Whether the destination is enabled as a return destination.
        address:
          $ref: '#/components/schemas/AddressRequest'
    AddressRequest:
      type: object
      description: The destination's address.
      required:
        - address1
        - city
        - country
        - country_code
      properties:
        name:
          type: [string, "null"]
          example: Main Warehouse
          description: The name associated with the address.
        company:
          type: [string, "null"]
          example: Universal Exports
          description: The company residing at the address.
        address1:
          type: string
          example: 123 Main St
          description: The street address of the destination.
        address2:
          type: [string, "null"]
          example: Unit 456
          description: The secondary address details of the destination.
        city:
          type: string
          example: Columbus
        state:
          type: [string, "null"]
          example: Ohio
        zip:
          type: [string, "null"]
          example: '43210'
        country:
          type: string
          example: 'United States'
        country_code:
          type: string
          example: 'US'
        phone:
          type: [string, "null"]
          example: '+1-678-999-8212'
          description: The phone number associated with the address.
    NotFoundResponse:
      type: object
      properties:
        code:
          type: string
          example: 'NOT_FOUND'
        message:
          type: string
          example: 'The destination could not be found. Please verify that the provided id is correct.'
    UnauthorizedResponse:
      type: object
      required:
        - errors
      properties:
        errors:
          type: string
          example: 'Unauthorized.'
    UnprocessableResponse:
      type: object
      properties:
        message:
          type: string
          example: 'The name field is required.'
    DestinationLimitExceeded:
      type: object
      properties:
        code:
          type: string
          example: 'DESTINATION_LIMIT_EXCEEDED'
        message:
          type: string
          example: 'You have reached the destination limit. Please check your settings.'
    BadRequestResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: 'INVALID_PARAMETER'
            message:
              type: string
              example: 'Invalid destination id. Expected an integer.'
    InternalServerErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: 'INTERNAL_SERVER_ERROR'
            message:
              type: string
              example: 'One or more destinations do not have an address.'
  securitySchemes:
    api_key:
      type: 'apiKey'
      name: 'X-Authorization'
      in: 'header'
