handy Orders API

The Orders API from handy — 2 operation(s) for orders.

OpenAPI Specification

handy-orders-api-openapi.yml Raw ↑
swagger: '2.0'
info:
  title: Handy’s Partner Bookings Orders API
  description: "<p>The Handy Partner API offers retailers fixed price installation\nservices that can be added to their eCommerce site or in-store checkout experience.\nTo start using the Handy Partner API, contact partners-eng@handy.com in order to\n        get access to the Sandbox.</p>\n        <p>Once you are ready to move to prod, we will walk you through quick authentication steps.</p>"
  version: v1
  contact: partnerships@handy.com
host: partners.services.handy.com
schemes:
- https
tags:
- name: Orders
paths:
  /api/v1/orders:
    post:
      summary: Create Order
      description: "Creates an order using one or more product SKUs that correspond to Angi services.\n\n ### Multi-Item Orders \n **Multiple items with the same product SKU** - If a customer purchased multiple Angi services with the **same** product SKU in a single basket, **only create one object for this product SKU** in the `products` array and indicate the quantity within the product object in the `product[:order_details][:quantity]` field. \n\n *Example of three products with the same SKU (quantity set on `order_details`).* \n\n ``` \n\n \"products\": [\n    {\n        \"sku\": \"ANGI1234\",\n        \"product_info\": {...},\n        \"order_details\": {\n            \"quantity\": 3,\n            ...\n        },\n        \"scheduling_details\": {}\n    }\n] \n\n``` \n\n **Multiple items with different product SKUs** - If there are multiple product SKUs that correspond to more than one Angi service, create `product` objects for each of the SKUs indicating their associated quantities. \n\n *Example of three products with the same SKU (quantity set on `order_details`) and one product with a different SKU on the same order.*  \n\n ``` \n\n \"products\": [\n    {\n        \"sku\": \"ANGI1234\",\n        \"product_info\": {...},\n        \"order_details\": {\n            \"quantity\": 3,\n            ...\n        },\n        \"scheduling_details\": {}\n    },\n    {\n        \"sku\": \"ANGI5555\",\n        \"product_info\": {...},\n        \"order_details\": {\n            \"quantity\": 1,\n            ...\n        },\n        \"scheduling_details\": {}\n    }\n] \n\n``` \n\n \n\n **Do NOT** create product objects for product SKUs that do not map/correspond to an Angi service. \n\n ### Success and Webhooks \n When an order is successfully created you will receive the `201` status code which is an acknowledgment from Angi that your order was created successfully. If your partner configuration has been set up with webhooks, after submitting an order creation you will receive either `booking_confirmed`, `booking_rescheduled`, or both (depending on your configuration). These webhooks will provide you with the most up-to-date booking/scheduling information associated with the submitted order. (See the Webhooks tab for more information around webhooks request body structure and more)."
      tags:
      - Orders
      consumes:
      - application/json
      produces:
      - application/json
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        type: string
        description: Your assigned partner ID
        example: partner_name
      - name: HDY-TIMESTAMP
        in: header
        type: string
        description: Seconds since epoch UTC
        example: '1525361611'
      - name: HDY-SIGNATURE
        in: header
        type: string
        description: 'Signature generated using your private key.

          Click <a href=''https://github.com/Handybook/API-Request-Signing'' target=''_blank''>here</a> to learn how.'
        example: OF5xI0LbLXHkFBLyNa8l..XHk=
      - name: request_body
        in: body
        schema:
          $ref: '#/definitions/order_creation_params'
      responses:
        '201':
          description: Created. Order created with required bookings
          schema:
            type: object
            properties:
              order:
                $ref: '#/definitions/order_response'
        '400':
          description: Bad request error, check order details passed in on request.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Invalid user details
              code:
                type: string
                example: user_details_invalid
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: object
                example:
                  email:
                  - is an invalid
            required:
            - message
            - code
            - error_uuid
            - more_info
        '401':
          description: Unauthorized error, check authentication mechanism.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Unauthorized request
              code:
                type: string
                example: unauthorized
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '422':
          description: Unprocessable entity error, check SKU provided on request.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Invalid SKU provided
              code:
                type: string
                example: invalid_sku
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '409':
          description: Conflict error, order has already been processed. No further action required.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Order has already been processed. You do no need to do anything else.
              code:
                type: string
                example: order_already_processed
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '500':
          description: Internal server error, order creation failed.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Failed to create the order
              code:
                type: string
                example: order_creation_failed
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
    get:
      summary: Recent Orders
      description: "Get a list of partner specific orders created in the API. A useful aspect of this endpoint is that you can check the status of an order that has been submitted as well as receiving the status of each individual `order_product` within the parent order. The endpoint is flexible in that you can query based on `order_id` (same as `partner_order_id`), `user_id` (the ID assigned to the consumer upon order creation and returned to the partner in the response), `booking_guid` (the ID assigned to the booking upon order creation and returned to the partner in the response). \n\n### Pagination \n\n The `page` and `size` query parameters can be used to receive paginated responses from the recent orders API. Example scenario: I have 4 orders in total that will be returned by this API call. If I call this endpoint with no query parameters I will receive all 4 orders. But if I want each page to have a size of 2 orders and I want to receive the 2nd page of orders, I would pass in query parameters `?size=2&page=2`. I will receive the last 2 orders in the response."
      tags:
      - Orders
      consumes:
      - application/json
      produces:
      - application/json
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        type: string
        description: Your assigned partner ID
        example: partner_name
      - name: HDY-TIMESTAMP
        in: header
        type: string
        description: Seconds since epoch UTC
        example: '1525361611'
      - name: HDY-SIGNATURE
        in: header
        type: string
        description: 'Signature generated using your private key.

          Click <a href=''https://github.com/Handybook/API-Request-Signing'' target=''_blank''>here</a> to learn how.'
        example: OF5xI0LbLXHkFBLyNa8l..XHk=
      - name: size
        in: query
        type: integer
        description: Number of orders per page (optional, used for pagination. See endpoint description above for more info).
        required: false
        default: 10
        example: 1
      - name: page
        in: query
        type: integer
        description: Page number for paginated list of orders (optional, see endpoint description above for more info).
        default: 1
        example: 2
      - name: order_id
        in: query
        type: string
        description: Filter orders by `partner_order_id` that was passed in on the order creation request (optional).
        example: '110001023'
      - name: user_id
        in: query
        type: string
        description: 'Filter orders by `user_id` (optional). This is the same `user_id` that is returned in the response from order creation. '
        example: xzvdfhryhbdbe
      - name: booking_guid
        in: query
        type: string
        description: Filter orders by booking_guid (optional). This is the same ID that is returned in the `booking_id` field on order creation.
        example: w813v41k6lxzj5g
      responses:
        '200':
          description: OK
          schema:
            type: object
            properties:
              orders:
                type: array
                items:
                  $ref: '#/definitions/recent_orders_response'
              total:
                type: integer
                description: The number of orders returned in the `orders` response array.
                example: 1
        '401':
          description: Unauthorized error, check authentication mechanism.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Unauthorized request
              code:
                type: string
                example: unauthorized
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '500':
          description: Internal server error.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Internal server error.
              code:
                type: string
                example: order_creation_failed
              more_info:
                type: string
                example: An unexpected error has occurred.
              error_uuid:
                $ref: '#/definitions/error_uuid'
  /api/v1/orders/{partner_order_id}:
    get:
      summary: Retrieve Order
      description: Retrieve information about an order by `partner_order_id`. A useful aspect of this endpoint is that you can check the status of an order that has been submitted as well as receiving the status of each individual `order_product` within the parent order.
      tags:
      - Orders
      consumes:
      - application/json
      produces:
      - application/json
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        type: string
        description: Your assigned partner ID
        example: partner_name
      - name: HDY-TIMESTAMP
        in: header
        type: string
        description: Seconds since epoch UTC
        example: '1525361611'
      - name: HDY-SIGNATURE
        in: header
        type: string
        description: 'Signature generated using your private key.

          Click <a href=''https://github.com/Handybook/API-Request-Signing'' target=''_blank''>here</a> to learn how.'
        example: OF5xI0LbLXHkFBLyNa8l..XHk=
      - name: partner_order_id
        in: path
        type: string
        required: true
        description: The `partner_order_id` that was used on order creation.
        example: '110001023'
      responses:
        '200':
          description: OK. Order retrieved.
          schema:
            type: object
            properties:
              order:
                $ref: '#/definitions/retrieve_order_response'
        '401':
          description: Unauthorized error, check authentication mechanism.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Unauthorized request
              code:
                type: string
                example: unauthorized
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '404':
          description: Not found error.
          schema:
            type: object
            properties:
              message:
                type: string
                example: The order was not found
              code:
                type: string
                example: order_not_found
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '500':
          description: Internal server error.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Internal server error.
              code:
                type: string
                example: order_creation_failed
              more_info:
                type: string
                example: An unexpected error has occurred.
              error_uuid:
                $ref: '#/definitions/error_uuid'
    patch:
      summary: Update Order
      description: "Update `delivery_date`, `service_date` or `service_datetime` for products or service bookings associated with an order in the `scheduling_details` object. \n\n ### Multi-Item Orders \n\n When an order is originally created with multiple items, items that have a SKU that maps to the same service these will already be created as one booking. In the case of multiple products in the cart with SKUs that map to different services, multiple bookings will have been created. If the multi-item orders have not experienced any consolidation, updates to the order will impact all items in the booking. The update method will not allow for changing properties other than scheduling on the booking. In a case where the customer purchases more products, this should be created as a new order rather than trying to update items on the existing order. \n\n ### Updating Consolidated Orders \n\n When an order is submitted that can been consolidated into an existing booking for a consumer, an update on an individual order will operate on the elements of the booking that are associated with that particular order. For example, if I sent in a `delivery_date` update on the second order that is a week in the future but this order was consolidated into the first booking, a new booking will be created with the elements of the second partner order. (Webhooks will be sent for both partner orders). \n\n ### Success and Webhooks \n\n When an order is successfully updated you will receive the `200` status code which is an acknowledgment from Angi that your order was updated. If your partner configuration has been set up with webhooks, after submitting an order creation you will receive a `booking_rescheduled`. This webhook will provide you with the most up-to-date booking/scheduling information associated with the updated order. (See the Webhooks tab for more information around webhooks request body structure and more)."
      tags:
      - Orders
      consumes:
      - application/json
      produces:
      - application/json
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        type: string
        description: Your assigned partner ID
        example: partner_name
      - name: HDY-TIMESTAMP
        in: header
        type: string
        description: Seconds since epoch UTC
        example: '1525361611'
      - name: HDY-SIGNATURE
        in: header
        type: string
        description: 'Signature generated using your private key.

          Click <a href=''https://github.com/Handybook/API-Request-Signing'' target=''_blank''>here</a> to learn how.'
        example: OF5xI0LbLXHkFBLyNa8l..XHk=
      - name: partner_order_id
        in: path
        type: string
        required: true
        description: The partner_order_id that was used to create the order.
        example: 110001023xx455
      - name: request_body
        in: body
        schema:
          $ref: '#/definitions/update_order_req_body'
        required: true
      responses:
        '200':
          description: Order updated successfully.
          schema:
            type: object
            properties:
              order:
                $ref: '#/definitions/order_response'
        '400':
          description: Bad request error, check scheduling_details.
          schema:
            type: object
            properties:
              message:
                type: string
                example: requested reschedule time is in the past
              code:
                type: string
                example: reschedule_request_date_in_past
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: object
                example:
                  code: reschedule_request_date_in_past
                  data:
                  - detail: requested reschedule time is in the past
            required:
            - message
            - code
            - error_uuid
            - more_info
        '403':
          description: Forbidden. Check auth credentials for your partner.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Access denied.
              code:
                type: string
                example: forbidden_access_denied
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: object
                example:
                  code: forbidden_access_denied
                  data:
                  - detail: Forbidden.
        '404':
          description: Order not found, check partner_order_id on request.
          schema:
            type: object
            properties:
              message:
                type: string
                example: 'Order #110001023 was not found'
              code:
                type: string
                example: order_not_found
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: string
                example: The order was not found
            required:
            - message
            - code
            - error_uuid
            - more_info
        '422':
          description: Unprocessable entity error, check scheduling details.
          schema:
            type: object
            properties:
              message:
                type: string
                example: reschedule requests must be made at least 24 hours before the booking start time
              code:
                type: string
                example: reschedule_request_not_within_reschedule_window
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: object
                example:
                  code: reschedule_request_not_within_reschedule_window
                  data:
                  - detail: reschedule requests must be made at least 24 hours before the booking start time
            required:
            - message
            - code
            - error_uuid
            - more_info
        '500':
          description: Internal server error. Order NOT updated.
          schema:
            type: object
            properties:
              message:
                type: string
                example: internal server error
              code:
                type: string
                example: internal_server_error
              error_uuid:
                $ref: '#/definitions/error_uuid'
              more_info:
                type: object
                example:
                  code: internal_server_error
                  data:
                  - detail: internal server error
            required:
            - message
            - code
            - error_uuid
            - more_info
    delete:
      summary: Cancel
      description: "The endpoint can be used to cancel a order which in turn will cancel bookings associated with the order. \n Endpoint has some restrictions which would mean a booking cannot be cancelled. Some of the restrictions are as follows `order_already_cancelled`, `booking_already_cancelled`, `booking_already_completed`, `booking_already_started`, can see the examples in the `422` block. \n\n **Note** The Api endpoint is a blanket delete call to cancel all bookings associated with an order, continue reading for different scenarios of cancellations. \n\n ### Multi-Product Order \n\n If the order has multiple products, the order might have multiple bookings. A cancellation request for a order that has two products, will result in cancelling of both bookings and a slightly different looking response body with a `200` status code \n\n \n\n ``` {\n    \"order\": {\n        \"partner_order_id\": \"110001023\",\n        \"user_id\": \"ojxyzrldy81gl28\",\n        \"address_id\": \"71npkxynjqog2w6\",\n        \"products\": [\n            {\n                \"booking_id\": \"v50r6460w43nd1p\",\n                \"charge_amount_in_cents\": 9099,\n                \"charge_currency\": \"USD\",\n                \"customer_price_in_cents\": null,\n                \"default_schedule\": false,\n                \"delivery_date\": \"2018-02-05\",\n                \"error\": null,\n                \"line_number\": \"1\",\n                \"name\": \"Shower System 1 Pro Installation\",\n                \"product_category\": null,\n                \"order_date\": \"2024-06-27T23:01:48.000Z\",\n                \"order_product_id\": \"k5o3pmrvq7x4qjg\",\n                \"partner_machine_name\": \"partner_name\",\n                \"partner_order_id\": \"110001023\",\n                \"product_status\": \"cancelled\",\n                \"product_weight_in_lbs\": 50,\n                \"quantity\": 1,\n                \"service_date\": \"2024-06-28\",\n                \"service_datetime\": null,\n                \"sku\": \"Example1\",\n                \"wholesale_price_in_cents\": null,\n                \"customer_scheduling_preferences\": null\n            },\n            {\n                \"booking_id\": \"rk3dx4wpy2q76o9\",\n                \"charge_amount_in_cents\": 9099,\n                \"charge_currency\": \"USD\",\n                \"customer_price_in_cents\": null,\n                \"default_schedule\": false,\n                \"delivery_date\": \"2018-02-05\",\n                \"error\": null,\n                \"line_number\": \"1\",\n                \"name\": \"Shower System 1 Pro Installation\",\n                \"product_category\": null,\n                \"order_date\": \"2024-06-27T23:01:48.000Z\",\n                \"order_product_id\": \"nxr0j1py31eoqpd\",\n                \"partner_machine_name\": \"partner_name\",\n                \"partner_order_id\": \"110001023\",\n                \"product_status\": \"cancelled\",\n                \"product_weight_in_lbs\": 50,\n                \"quantity\": 1,\n                \"service_date\": \"2024-06-28\",\n                \"service_datetime\": null,\n                \"sku\": \"Example2\",\n                \"wholesale_price_in_cents\": null,\n                \"customer_scheduling_preferences\": null\n            }\n        ],\n        \"created_at\": \"2024-06-27T23:01:48.000Z\",\n        \"processing_status\": \"complete\",\n        \"partner_machine_name\": \"partner_name\",\n        \"metadata\": {}\n    }\n} \n\n``` \n\n When a order contains multiple bookings and one of the bookings is completed or started and a `cancel` request is sent, the api will cancel booking that was not started and return the `booking_id` of the booking that was not cancelled with a `422` status code. \n\n ```\n {\n    \"message\": \"Some bookings within partner order 110001023 could not be cancelled: k1vy62j8940mo7e.\",\n    \"code\": \"booking_already_completed\",\n    \"more_info\": \"Booking has been completed\",\n    \"error_uuid\": \"f8db8791a9db3a71e06a5563901291ed\"\n} \n\n``` \n\n ### Success and Webhooks\n\n When an order is successfully cancelled you will receive the 200 status code which is an acknowledgment from Angi that your order was cancelled. If your partner configuration has been set up with webhooks, after order is cancelled you will receive one or more `booking_cancelled` events, depending on how many bookings the order had. This webhook will provide you with the info that has `booking_id`, `partner-order_id` and `event_time`. (See the Webhooks tab for more information around webhooks request body structure and more). "
      tags:
      - Orders
      consumes:
      - application/json
      produces:
      - application/json
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        type: string
        description: Your assigned partner ID
        example: partner_name
      - name: HDY-TIMESTAMP
        in: header
        type: string
        description: Seconds since epoch UTC
        example: '1525361611'
      - name: HDY-SIGNATURE
        in: header
        type: string
        description: 'Signature generated using your private key.

          Click <a href=''https://github.com/Handybook/API-Request-Signing'' target=''_blank''>here</a> to learn how.'
        example: OF5xI0LbLXHkFBLyNa8l..XHk=
      - name: id
        in: path
        type: string
        required: true
        description: The Order's id
        example: '110001023'
      - name: reason
        in: query
        description: A reason for cancellation (optional). If passing a reason parameter it should be valid else will result in reason_not_found
        type: string
        example: partner_returned_item
      responses:
        '200':
          description: OK, Order cancelled successfully
          schema:
            type: object
            properties:
              order:
                $ref: '#/definitions/order_response'
        '400':
          description: Bad Request, Invalid reason code in query param
          schema:
            type: object
            properties:
              message:
                type: string
                example: Reason not found.
              code:
                type: string
                example: invalid_request_parameter
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '404':
          description: Order Not found
          schema:
            type: object
            properties:
              message:
                type: string
                example: The order was not found
              code:
                type: string
                example: order_not_found
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '409':
          description: Order already cancelled
          schema:
            type: object
            properties:
              message:
                type: string
                example: Order 1234567890 is already cancelled
              code:
                type: string
                example: order_already_cancelled
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '500':
          description: Order Cancellation failed, Internal server error.
          schema:
            type: object
            properties:
              message:
                type: string
                example: Some bookings within partner order 1234567890 could not be cancelled
              code:
                type: string
                example: booking_cancellation_failed
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
        '422':
          description: Order not cancelled, Booking already completed | Booking Already Cancelled | Booking already started
          schema:
            type: object
            properties:
              message:
                type: string
                example: Order 110001023 is already cancelled.
              code:
                type: string
                example: booking_already_cancelled
              error_uuid:
                $ref: '#/definitions/error_uuid'
            required:
            - message
            - code
            - error_uuid
definitions:
  sku:
    type: string
    example: HANDY1234
    description: The product identifier that has been allocated to the product you are submitting on this order request.
  order_creation_params:
    type: object
    properties:
      user:
        $ref: '#/definitions/user'
      address:
        $ref: '#/definitions/address'
      order:
        $ref: '#/definitions/order'
    required:
    - user
    - address
    - order
  retrieve_order_response:
    type: object
    properties:
      partner_order_id:
        type: string
        example: '110001023'
        description: The unique ID that is provided to Angi by the partner on order creation.
      user_id:
        type: string
        example: xzvdfhryhbdbe
        description: The unique ID that Angi has assigned to the consumer object that was created as a result of this order.
      address_id:
        type: string
        example: sfgethrethrt
        description: The unique ID that Angi has assigned the consumer's address object that was created as a result of this order.
      products:
        $ref: '#/definitions/recent_orders_product_responses'
      created_at:
        type: string
        example: '2018-05-02T22:21:49.000Z'
      processing_status:
        type: string
        example: complete
        description: "If a partner is unsure about what is going on with an order, this field can provide more detail. The following statuses can be returned in this field: \n\n`failed`: order creation has failed. \n\n`partial`: some order products within this order have been created but there are others that are still processing. To see the statuses of individual products within this order, find the product in the `products` array and look for its `product_status`. \n\n`complete`: order creation is complete. \n\n`in_progress`: order creation is in progress."
      partner_machine_name:
        type: string
        example: partner_name
        description: The unique partner name given to the partner (same one that is used in the HTTP headers).
      metadata:
        type: object
        x-nullable: true
        description: Metadata that was passed in by the partner.
  update_order_req_body:
    type: object
    description: Information about the order to update.
    properties:
      partner_order_id:
        description: This is optional. Be sure to put the `partner_order_id` in the path parameter, that one is required.
        type: string
        example: '110001023'
      products:
        type: array
        items:
          type: object
          properties:
            sku:
              $ref: '#/definitions/sku'
            order_details:
              $ref: '#/definitions/order_details_update'
            scheduling_details:
              $ref: '#/definitions/scheduling_details'
  product_info:
    type: object
    description: The information passed in this object will be used to create or

# --- truncated at 32 KB (46 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/handy/refs/heads/main/openapi/handy-orders-api-openapi.yml