CleanCloud Webhooks

Outbound webhooks that POST to a configured external URL when an event occurs. CleanCloud publishes 10 events - order.created (in-store), order.created (pickup and delivery), order.status_changed, order.pickup_rescheduled, order.delivery_rescheduled, order.nothing_to_pickup, order.deleted, customer.created, customer.updated, and customer.deleted - configured under Settings > Admin > Pickup and Delivery > API > Webhooks.

OpenAPI Specification

drycleancloud-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: CleanCloud API
  description: >-
    The CleanCloud API provides programmatic access to the CleanCloud
    point-of-sale and business-management platform for dry cleaners,
    laundromats, laundry services, and shoe repair businesses. It covers
    customers, orders and garments, products, price lists, inventory, pickup and
    delivery scheduling and routing, payments and subscriptions, invoices,
    promotions and loyalty, messaging, and reporting.


    All calls are HTTPS POST requests with a JSON body to
    https://cleancloudapp.com/api and return JSON. Authentication uses a
    per-account API token passed as the `api_token` field in the JSON request
    body (found in the CleanCloud admin under Settings > Admin > Pickup and
    Delivery > API). Because the token is a body field rather than an HTTP header
    or query parameter, it is modeled here as a required `api_token` property on
    each request schema rather than as an OpenAPI security scheme.


    API access requires a Grow or Grow+ subscription (Pro in Mexico) and is
    metered at 50,000 requests per month with a maximum of 3 requests per second;
    additional 25,000-request bundles are available. CleanCloud also emits
    outbound webhooks for order and customer events; those are documented in the
    provider apis.yml and review, not as request/response paths here.
  version: '1.0'
  contact:
    name: CleanCloud
    url: https://cleancloudapp.com
  x-authentication:
    scheme: api_token
    location: request body (JSON field `api_token`)
    note: >-
      Every endpoint requires the api_token field. It is not sent as an
      Authorization header or query parameter.
servers:
  - url: https://cleancloudapp.com/api
    description: CleanCloud production API
tags:
  - name: Customers
    description: Customer accounts, authentication, and password reset.
  - name: Orders
    description: Orders and the garments within them.
  - name: Products
    description: Products, price lists, and inventory.
  - name: Pickup and Delivery
    description: Recurring pickups, routing, scheduling, and driver location.
  - name: Payments
    description: Payments, cards, subscriptions, invoices, promotions, and loyalty.
  - name: Business and Reporting
    description: Business accounts, reporting, photos, groups, and referrals.
  - name: Messaging
    description: Customer/store messaging and push notification tokens.
paths:
  /addCustomer:
    post:
      operationId: addCustomer
      tags: [Customers]
      summary: Create a customer
      description: Creates a new customer account.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - $ref: '#/components/schemas/CustomerInput'
      responses:
        '200':
          description: The created customer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /updateCustomer:
    post:
      operationId: updateCustomer
      tags: [Customers]
      summary: Update a customer
      description: Updates fields on an existing customer identified by customerID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
                - $ref: '#/components/schemas/CustomerInput'
      responses:
        '200':
          description: The updated customer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /deleteCustomer:
    post:
      operationId: deleteCustomer
      tags: [Customers]
      summary: Delete a customer
      description: Deletes a customer account by customerID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
      responses:
        '200':
          description: Deletion result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getCustomer:
    post:
      operationId: getCustomer
      tags: [Customers]
      summary: Get customer(s)
      description: >-
        Retrieves a single customer by customerID, or a set of customers by a
        created/updated date range.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    customerID:
                      type: string
                      description: Retrieve a single customer by ID.
                    dateFrom:
                      type: string
                      description: Start of a created/updated date range (YYYY-MM-DD).
                    dateTo:
                      type: string
                      description: End of a created/updated date range (YYYY-MM-DD).
      responses:
        '200':
          description: One or more customers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Customers:
                    type: array
                    items:
                      $ref: '#/components/schemas/Customer'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /loginCustomer:
    post:
      operationId: loginCustomer
      tags: [Customers]
      summary: Authenticate a customer
      description: Authenticates a customer by email and password and returns the customer ID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerEmail, customerPassword]
                  properties:
                    customerEmail:
                      type: string
                    customerPassword:
                      type: string
      responses:
        '200':
          description: Authentication result with customer ID.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /passwordCustomer:
    post:
      operationId: passwordCustomer
      tags: [Customers]
      summary: Send password reset
      description: Triggers a password-reset email to the customer.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerEmail]
                  properties:
                    customerEmail:
                      type: string
      responses:
        '200':
          description: Reset email result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /addOrder:
    post:
      operationId: addOrder
      tags: [Orders]
      summary: Create an order
      description: Creates a new order for a customer with a list of products and a final total.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID, finalTotal, products]
                  properties:
                    customerID:
                      type: string
                    finalTotal:
                      type: number
                    products:
                      type: array
                      items:
                        $ref: '#/components/schemas/OrderProduct'
      responses:
        '200':
          description: The created order.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /updateOrder:
    post:
      operationId: updateOrder
      tags: [Orders]
      summary: Update an order
      description: Updates an order's details, status, or payment state.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [orderID]
                  properties:
                    orderID:
                      type: string
                    orderStatus:
                      type: string
                    paid:
                      type: boolean
      responses:
        '200':
          description: The updated order.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /deleteOrder:
    post:
      operationId: deleteOrder
      tags: [Orders]
      summary: Delete an order
      description: Deletes an order, optionally validating against its pickup time.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [orderID]
                  properties:
                    orderID:
                      type: string
                    checkPickupTime:
                      type: boolean
      responses:
        '200':
          description: Deletion result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getOrders:
    post:
      operationId: getOrders
      tags: [Orders]
      summary: List orders
      description: Retrieves orders filtered by customer, route, date, or status.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    customerID:
                      type: string
                    orderStatus:
                      type: string
                    dateFrom:
                      type: string
                    dateTo:
                      type: string
      responses:
        '200':
          description: A list of orders.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getGarment:
    post:
      operationId: getGarment
      tags: [Orders]
      summary: Get a garment
      description: Fetches a single garment by its barcode.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [barcode]
                  properties:
                    barcode:
                      type: string
      responses:
        '200':
          description: The requested garment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Garment'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getGarments:
    post:
      operationId: getGarments
      tags: [Orders]
      summary: List garments in an order
      description: Retrieves all garments belonging to an order.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [orderID]
                  properties:
                    orderID:
                      type: string
      responses:
        '200':
          description: A list of garments.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Garments:
                    type: array
                    items:
                      $ref: '#/components/schemas/Garment'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /updateGarment:
    post:
      operationId: updateGarment
      tags: [Orders]
      summary: Update a garment
      description: Updates a garment's color, notes, location, or status.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [barcode]
                  properties:
                    barcode:
                      type: string
                    color:
                      type: string
                    notes:
                      type: string
                    location:
                      type: string
                    status:
                      type: string
      responses:
        '200':
          description: The updated garment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Garment'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getProducts:
    post:
      operationId: getProducts
      tags: [Products]
      summary: List products
      description: Lists active products, optionally including parent products and upcharges.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    includeParents:
                      type: boolean
                    includeUpcharges:
                      type: boolean
      responses:
        '200':
          description: A list of products.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Products:
                    type: array
                    items:
                      $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getPriceLists:
    post:
      operationId: getPriceLists
      tags: [Products]
      summary: List price lists
      description: Retrieves all active price lists.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthBody'
      responses:
        '200':
          description: A list of price lists.
          content:
            application/json:
              schema:
                type: object
                properties:
                  PriceLists:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getInventory:
    post:
      operationId: getInventory
      tags: [Products]
      summary: Get inventory
      description: Fetches current inventory stock levels.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthBody'
      responses:
        '200':
          description: Current inventory levels.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Inventory:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /repeatPickup:
    post:
      operationId: repeatPickup
      tags: [Pickup and Delivery]
      summary: Create a recurring pickup
      description: Creates a scheduled recurring pickup for a customer.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
                    frequency:
                      type: string
                    dayOfWeek:
                      type: string
      responses:
        '200':
          description: The created recurring pickup.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /updateRepeatPickup:
    post:
      operationId: updateRepeatPickup
      tags: [Pickup and Delivery]
      summary: Update a recurring pickup
      description: Modifies an existing recurring pickup schedule.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [pickupID]
                  properties:
                    pickupID:
                      type: string
                    frequency:
                      type: string
                    dayOfWeek:
                      type: string
      responses:
        '200':
          description: The updated recurring pickup.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /deletePickup:
    post:
      operationId: deletePickup
      tags: [Pickup and Delivery]
      summary: Cancel a recurring pickup
      description: Cancels a recurring pickup.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [pickupID]
                  properties:
                    pickupID:
                      type: string
      responses:
        '200':
          description: Cancellation result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getPickups:
    post:
      operationId: getPickups
      tags: [Pickup and Delivery]
      summary: List recurring pickups
      description: Retrieves a customer's recurring pickups.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
      responses:
        '200':
          description: A list of recurring pickups.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Pickups:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getDates:
    post:
      operationId: getDates
      tags: [Pickup and Delivery]
      summary: Get available dates
      description: Returns available pickup/delivery dates with remaining slot counts.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    routeID:
                      type: string
      responses:
        '200':
          description: Available dates.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Dates:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getSlots:
    post:
      operationId: getSlots
      tags: [Pickup and Delivery]
      summary: Get time slots
      description: Returns available time slots for a route on a given day.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    routeID:
                      type: string
                    date:
                      type: string
      responses:
        '200':
          description: Available time slots.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Slots:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getRoute:
    post:
      operationId: getRoute
      tags: [Pickup and Delivery]
      summary: Resolve a route
      description: Determines the delivery route from coordinates or an address.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    address:
                      type: string
                    lat:
                      type: number
                    lng:
                      type: number
      responses:
        '200':
          description: The resolved route.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /driverLocation:
    post:
      operationId: driverLocation
      tags: [Pickup and Delivery]
      summary: Get driver location
      description: Returns the current driver location for an order.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [orderID]
                  properties:
                    orderID:
                      type: string
      responses:
        '200':
          description: The current driver location.
          content:
            application/json:
              schema:
                type: object
                properties:
                  lat:
                    type: number
                  lng:
                    type: number
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getPayments:
    post:
      operationId: getPayments
      tags: [Payments]
      summary: List payments
      description: Lists payments, optionally filtered by date.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    dateFrom:
                      type: string
                    dateTo:
                      type: string
      responses:
        '200':
          description: A list of payments.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Payments:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getInvoices:
    post:
      operationId: getInvoices
      tags: [Payments]
      summary: List invoices
      description: Retrieves invoices by customer, business account, or date.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  properties:
                    customerID:
                      type: string
                    businessID:
                      type: string
                    dateFrom:
                      type: string
                    dateTo:
                      type: string
      responses:
        '200':
          description: A list of invoices.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Invoices:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /addCard:
    post:
      operationId: addCard
      tags: [Payments]
      summary: Save a payment card
      description: Saves a card via a Stripe, Clearent, or Amazon payment token.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID, token]
                  properties:
                    customerID:
                      type: string
                    token:
                      type: string
                    provider:
                      type: string
                      enum: [stripe, clearent, amazon]
      responses:
        '200':
          description: The saved card.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /chargeCard:
    post:
      operationId: chargeCard
      tags: [Payments]
      summary: Charge a saved card
      description: Charges an amount to a customer's saved card.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID, amount]
                  properties:
                    customerID:
                      type: string
                    amount:
                      type: number
                    cardID:
                      type: string
      responses:
        '200':
          description: The charge result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getCards:
    post:
      operationId: getCards
      tags: [Payments]
      summary: List saved cards
      description: Lists a customer's saved cards, by provider.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
                    provider:
                      type: string
      responses:
        '200':
          description: A list of saved cards.
          content:
            application/json:
              schema:
                type: object
                properties:
                  Cards:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
  /setDefaultCard:
    post:
      operationId: setDefaultCard
      tags: [Payments]
      summary: Set default card
      description: Designates a saved card as the customer's default payment method.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID, cardID]
                  properties:
                    customerID:
                      type: string
                    cardID:
                      type: string
      responses:
        '200':
          description: Result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /addSubscription:
    post:
      operationId: addSubscription
      tags: [Payments]
      summary: Create a subscription
      description: Enables a recurring subscription for a customer (supports 3D Secure).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [customerID]
                  properties:
                    customerID:
                      type: string
                    planID:
                      type: string
      responses:
        '200':
          description: The created subscription.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /deleteSubscription:
    post:
      operationId: deleteSubscription
      tags: [Payments]
      summary: Cancel a subscription
      description: Cancels a customer's recurring subscription.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/AuthBody'
                - type: object
                  required: [subscriptionID]
                  properties:
                    subscriptionID:
                      type: string
      responses:
        '200':
          description: Cancellation result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /getSubscription:
    post:
      operationId: getSubscription
      tags: [Payments]
      summary: Get a subscription
  

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