handy Orders API

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

Operations 5

POST /api/v1/orders Create Order
GET /api/v1/orders Recent Orders
GET /api/v1/orders/{partner_order_id} Retrieve Order
PATCH /api/v1/orders/{partner_order_id} Update Order
DELETE /api/v1/orders/{partner_order_id} Cancel

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/handy-orders-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

handy-orders-api-openapi.yml Raw ↑
openapi: 3.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
servers:
- url: https://partners.services.handy.com
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
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        description: Your assigned partner ID
        example: partner_name
        schema:
          type: string
      - name: HDY-TIMESTAMP
        in: header
        description: Seconds since epoch UTC
        example: '1525361611'
        schema:
          type: string
      - name: HDY-SIGNATURE
        in: header
        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=
        schema:
          type: string
      responses:
        '201':
          description: Created. Order created with required bookings
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/order_response'
        '400':
          description: Bad request error, check order details passed in on request.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Invalid user details
                  code:
                    type: string
                    example: user_details_invalid
                  error_uuid:
                    $ref: '#/components/schemas/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.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Unauthorized request
                  code:
                    type: string
                    example: unauthorized
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '422':
          description: Unprocessable entity error, check SKU provided on request.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Invalid SKU provided
                  code:
                    type: string
                    example: invalid_sku
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '409':
          description: Conflict error, order has already been processed. No further action required.
          content:
            application/json:
              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: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '500':
          description: Internal server error, order creation failed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Failed to create the order
                  code:
                    type: string
                    example: order_creation_failed
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/order_creation_params'
    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
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        description: Your assigned partner ID
        example: partner_name
        schema:
          type: string
      - name: HDY-TIMESTAMP
        in: header
        description: Seconds since epoch UTC
        example: '1525361611'
        schema:
          type: string
      - name: HDY-SIGNATURE
        in: header
        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=
        schema:
          type: string
      - name: size
        in: query
        description: Number of orders per page (optional, used for pagination. See endpoint description above for more info).
        required: false
        example: 1
        schema:
          type: integer
          default: 10
      - name: page
        in: query
        description: Page number for paginated list of orders (optional, see endpoint description above for more info).
        example: 2
        schema:
          type: integer
          default: 1
      - name: order_id
        in: query
        description: Filter orders by `partner_order_id` that was passed in on the order creation request (optional).
        example: '110001023'
        schema:
          type: string
      - name: user_id
        in: query
        description: 'Filter orders by `user_id` (optional). This is the same `user_id` that is returned in the response from order creation. '
        example: xzvdfhryhbdbe
        schema:
          type: string
      - name: booking_guid
        in: query
        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
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/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.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Unauthorized request
                  code:
                    type: string
                    example: unauthorized
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '500':
          description: Internal server error.
          content:
            application/json:
              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: '#/components/schemas/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
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        description: Your assigned partner ID
        example: partner_name
        schema:
          type: string
      - name: HDY-TIMESTAMP
        in: header
        description: Seconds since epoch UTC
        example: '1525361611'
        schema:
          type: string
      - name: HDY-SIGNATURE
        in: header
        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=
        schema:
          type: string
      - name: partner_order_id
        in: path
        required: true
        description: The `partner_order_id` that was used on order creation.
        example: '110001023'
        schema:
          type: string
      responses:
        '200':
          description: OK. Order retrieved.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/retrieve_order_response'
        '401':
          description: Unauthorized error, check authentication mechanism.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Unauthorized request
                  code:
                    type: string
                    example: unauthorized
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '404':
          description: Not found error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: The order was not found
                  code:
                    type: string
                    example: order_not_found
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '500':
          description: Internal server error.
          content:
            application/json:
              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: '#/components/schemas/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
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        description: Your assigned partner ID
        example: partner_name
        schema:
          type: string
      - name: HDY-TIMESTAMP
        in: header
        description: Seconds since epoch UTC
        example: '1525361611'
        schema:
          type: string
      - name: HDY-SIGNATURE
        in: header
        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=
        schema:
          type: string
      - name: partner_order_id
        in: path
        required: true
        description: The partner_order_id that was used to create the order.
        example: 110001023xx455
        schema:
          type: string
      responses:
        '200':
          description: Order updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/order_response'
        '400':
          description: Bad request error, check scheduling_details.
          content:
            application/json:
              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: '#/components/schemas/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.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Access denied.
                  code:
                    type: string
                    example: forbidden_access_denied
                  error_uuid:
                    $ref: '#/components/schemas/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.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: 'Order #110001023 was not found'
                  code:
                    type: string
                    example: order_not_found
                  error_uuid:
                    $ref: '#/components/schemas/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.
          content:
            application/json:
              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: '#/components/schemas/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.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: internal server error
                  code:
                    type: string
                    example: internal_server_error
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                  more_info:
                    type: object
                    example:
                      code: internal_server_error
                      data:
                      - detail: internal server error
                required:
                - message
                - code
                - error_uuid
                - more_info
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/update_order_req_body'
        required: true
    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
      parameters:
      - name: HDY-PARTNER-ID
        in: header
        description: Your assigned partner ID
        example: partner_name
        schema:
          type: string
      - name: HDY-TIMESTAMP
        in: header
        description: Seconds since epoch UTC
        example: '1525361611'
        schema:
          type: string
      - name: HDY-SIGNATURE
        in: header
        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=
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: The Order's id
        example: '110001023'
        schema:
          type: string
      - 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
        example: partner_returned_item
        schema:
          type: string
      responses:
        '200':
          description: OK, Order cancelled successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/order_response'
        '400':
          description: Bad Request, Invalid reason code in query param
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Reason not found.
                  code:
                    type: string
                    example: invalid_request_parameter
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '404':
          description: Order Not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: The order was not found
                  code:
                    type: string
                    example: order_not_found
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '409':
          description: Order already cancelled
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Order 1234567890 is already cancelled
                  code:
                    type: string
                    example: order_already_cancelled
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '500':
          description: Order Cancellation failed, Internal server error.
          content:
            application/json:
              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: '#/components/schemas/error_uuid'
                required:
                - message
                - code
                - error_uuid
        '422':
          description: Order not cancelled, Booking already completed | Booking Already Cancelled | Booking already started
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Order 110001023 is already cancelled.
                  code:
                    type: string
                    example: booking_already_cancelled
                  error_uuid:
                    $ref: '#/components/schemas/error_uuid'
                required:
                - message
                - code
       

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