> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upwell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Set customer invoice email recipients by source system id

> Replace the invoice email recipients for the customer identified by `sourceSystem` + `sourceSystemId` (query parameters). Use this to keep Upwell in sync when the AP contact changes in your TMS.

**Behavior:**
- `input.emailAddresses` is the **full replacement list**. Each entry may itself be comma- or semicolon-separated (e.g. `"ap@acme.com; cc@acme.com"`). Addresses are trimmed, lowercased and de-duplicated.
- Every address is validated; any malformed address rejects the whole request and nothing is written.
- Writes the customer's **email** delivery method only. Portal and EDI delivery methods are never modified. If the customer has no email delivery method, one is created.
- Only the recipient list changes. Other delivery settings (subject, schedule, delivery mode, conditional recipients) are preserved.
- Delivery routing is written only when your organization has delivery routing switched on (Customer Settings → Delivery Routing). Then the customer's default routing rule is updated (or created) with the same recipients, and only the rule's **primary** target is replaced: any additional targets on that rule keep their own recipients and keep receiving routed invoices. The delivery method and the routing rule are written together: if the routing write fails, the delivery method change is rolled back. With routing off, routing rules are not read or changed and `routingRuleId` is `null` in the response.
- An empty `emailAddresses` list is rejected unless `input.forceClearRecipients` is `true`. A forced clear clears the email delivery method's recipients only; routing rules require at least one recipient and are left unchanged (`routingRuleId` is `null` in the response), so routed invoice email can keep going to the existing routing targets.
- `sourceSystem` matches case-insensitively; `sourceSystemId` must match exactly. The request is rejected if no customer, or more than one, matches.

**Errors:** a rejected request still returns HTTP `200`. The body has no `setCustomerEmailDeliveryRecipientsBySourceSystemId` object and instead carries the error message (for example `Invalid email address(es): ...`). Check for the result object before reading it.



## OpenAPI

````yaml /api-reference/openapi.json put /api/rest/customer_delivery_recipients
openapi: 3.1.0
info:
  description: >-
    Upwell is Accounts Receivable automation software for the logistics
    industry. We serve freight brokers, carriers, factors, and anyone who needs
    to get transportation invoices paid.


    Learn more at:


    - [Upwell.com](https://upwell.com)
  title: Upwell REST API
  version: 3.42.1
  termsOfService: https://upwell.com/legal
  contact:
    name: Upwell
    url: https://upwell.com
    email: contact@upwell.com
servers:
  - url: https://api.upwell.com
    description: Production server
  - url: https://staging.api.upwell.com
    description: Staging server
security:
  - ApiKeyAuth: []
tags:
  - name: Addresses
    description: >-
      **Core.** A typed physical address owned by one parent record — a
      customer, carrier, company, contact, or a shipment's pickup/consignee
      slot. Addresses are **not** shared master data: they are never
      deduplicated by content, and they carry no
      `sourceSystem`/`sourceSystemId`, so store the returned `addr_` id
      yourself. Embed an address when you create its parent; update it in a
      separate call. See [Working with addresses](/conventions/addresses).
  - name: Bill Line Items
    description: >-
      **Accounts payable.** Priced rows on a bill. Create, update, and delete
      only — there is no list endpoint, so read them through the parent bill.
  - name: Bill Payments
    description: >-
      **Accounts payable.** A payment that settles what you owe a carrier. A
      bill payment has no direct link to a bill — the relationship runs through
      its line items. See [Recording carrier
      payments](/api-guides/carrier-invoice-submission#recording-carrier-payments).
  - name: Bills
    description: >-
      **Accounts payable.** The expected payable synced from your TMS — what
      Upwell audits an incoming carrier invoice against. A bill is owed to
      *either* a carrier *or* a vendor, never both. See [Syncing foundation
      entities](/api-guides/syncing-foundation-entities).
  - name: Carrier Invoice Approval Requests
    description: >-
      **Accounts payable.** A pending approval decision Upwell hands to your
      system to resolve. See [Responding to an approval
      request](/api-guides/carrier-invoice-approval).
  - name: Carrier Invoice Documents
    description: >-
      **Accounts payable.** Documents attached to a carrier invoice — the
      invoice scan, BOL, POD, notice of assignment. Listed separately from
      **Carrier Invoices** because these operate on the document list rather
      than the invoice record itself.
  - name: Carrier Invoices
    description: >-
      **Accounts payable.** What a carrier actually billed you — the received
      payable, as opposed to the expected **Bill**. Create is de-duplicated
      **asynchronously**, not on the request, so a retry can briefly create a
      live duplicate: read
      [Re-submitting](/api-guides/carrier-invoice-submission#re-submitting)
      before you build retry logic.
  - name: Carrier Payment Line Items
    description: >-
      **Accounts payable.** How a bill payment splits across the bills it
      settles — the payables counterpart to **Customer Payment Line Items**.
      Build against `billId`. `billPaymentId` is **not** writable over the API
      by any role — the column exists on the table but is granted to none of
      them, so it is not part of the public insert input.
  - name: Carriers
    description: >-
      **Core.** Who hauls the freight and gets paid. Unlike customers,
      re-posting an existing `(sourceSystem, sourceSystemId)` pair **silently
      succeeds without updating any other field** — use `PUT` to change an
      existing carrier. See [Syncing foundation
      entities](/api-guides/syncing-foundation-entities).
  - name: Companies
    description: >-
      **Core.** **Your own** legal-entity or division record — *not* a customer.
      If you are looking for the party you bill and collect from, use
      **Customers** instead. Most integrations need only one company and rarely
      touch this endpoint.
  - name: Customer Payment Line Items
    description: >-
      **Accounts receivable.** How one customer payment splits across the
      invoices it pays — the unit that makes cash application work when a single
      check covers many invoices.
  - name: Customer Payments
    description: >-
      **Accounts receivable.** An incoming remittance from a customer, applied
      to invoices through its line items. Line-item amounts need not sum to the
      payment total — a remittance can be partially applied and reconciled
      later. See [Recording customer payments](/api-guides/customer-payments).
  - name: Customers
    description: >-
      **Core.** Who you bill and collect from (the shipper). Re-posting an
      existing `(sourceSystem, sourceSystemId)` pair returns `400 Uniqueness
      violation` — use `PUT` to update. **Deleting a customer also deletes their
      invoices**, so deactivate rather than delete.
  - name: Document Reference Specifications
    description: >-
      **Core.** Per-customer (or tenant-wide) rules describing what a reference
      number should look like, used to validate a reference's label and format.
      A niche configuration object that most integrations never need to touch.
  - name: Documents
    description: >-
      **Core.** A file — BOL, POD, rate confirmation, invoice scan. Usually
      attached to a shipment, invoice, or carrier invoice, though purchase
      orders and vendor invoices are uploaded standalone. Use the [two-step
      presigned-URL
      flow](/conventions/documents#document-upload-two-step-presigned-url) for
      anything large or unclassified.
  - name: Invoice Approval
    description: >-
      **Accounts receivable.** Queue and approval endpoints for customer
      invoices awaiting sign-off before they are delivered.
  - name: Invoice Documents
    description: >-
      **Accounts receivable.** Documents attached to a customer invoice.
      Documents already on a linked shipment appear on the invoice
      automatically, so you usually do not need to upload them twice.
  - name: Invoice Line Items
    description: >-
      **Accounts receivable.** Priced rows on a customer invoice — line haul,
      fuel surcharge, accessorials. They sum to the invoice total.
  - name: Invoice Shipments
    description: >-
      **Accounts receivable.** The link between a customer invoice and the
      shipments it bills. Use these endpoints to add or remove a shipment
      **after** the invoice already exists; linking or unlinking triggers a
      background re-sync of that shipment's documents onto the invoice.
  - name: Invoices
    description: >-
      **Accounts receivable.** What you bill your customer. An unqualified
      "invoice" always means this one — the customer/AR invoice, never the
      carrier's. See [Managing customer
      invoices](/api-guides/customer-invoices).
  - name: Purchase Orders
    description: >-
      **Accounts payable.** Inbound customer purchase orders parsed from a
      standalone PDF upload, including combined PDFs that Upwell splits into one
      record per document. See [Purchase orders and vendor
      invoices](/api-guides/purchase-orders-and-vendor-invoices).
  - name: Rules
    description: >-
      **Core.** Configurable if-this-then-that policies Upwell evaluates during
      processing — require a document, raise an exception, route by SCAC. Which
      fields you populate depends on the rule's `type`; see [Rules: three
      shapes](/conventions/rules).
  - name: Shipment Documents
    description: >-
      **Core.** Documents attached to a shipment. These propagate to invoices
      linked to that shipment, so uploading once is usually enough. See [Working
      with shipment documents](/api-guides/shipment-documents).
  - name: Shipment Line Items
    description: >-
      **Core.** Cargo and freight metadata on a shipment — commodity
      description, NMFC class, handling units, package counts, weight, hazmat
      flag. **Not** priced rows: unlike invoice, bill, and payment line items,
      these carry no rate or amount field at all.
  - name: Shipments
    description: >-
      **Core.** The freight movement (load) — the hub that invoices, bills, and
      documents hang off. `shipmentId` is required and has no server default.
      Pickup and consignee addresses can be embedded on create or attached later
      via `pickupAddressId`/`consigneeAddressId` on update — both are accepted
      even though this reference currently under-reports the update input. See
      [Working with addresses](/conventions/addresses).
  - name: Stops
    description: >-
      **Core.** Ordered points on a shipment's route — pickup, delivery,
      terminal, cross-dock. Populate `stopType`; the separate constrained `type`
      field is only partially adopted in practice. Deleting a shipment deletes
      its stops.
  - name: Vendor Invoices
    description: >-
      **Accounts payable.** Generic, non-freight vendor AP invoices parsed from
      a standalone PDF upload, matched to a **Purchase Order** when one exists.
      See [Purchase orders and vendor
      invoices](/api-guides/purchase-orders-and-vendor-invoices).
  - name: Vendors
    description: >-
      **Accounts payable.** A payable party that isn't a hauling carrier — a
      lumper service, a factor, a non-freight supplier. Both `sourceSystem` and
      `sourceSystemId` are required. Delete is **permanent** (there is no soft
      delete) and fails while any bill still references the vendor.
paths:
  /api/rest/customer_delivery_recipients:
    put:
      tags:
        - Customers
      summary: Set customer invoice email recipients by source system id
      description: >-
        Replace the invoice email recipients for the customer identified by
        `sourceSystem` + `sourceSystemId` (query parameters). Use this to keep
        Upwell in sync when the AP contact changes in your TMS.


        **Behavior:**

        - `input.emailAddresses` is the **full replacement list**. Each entry
        may itself be comma- or semicolon-separated (e.g. `"ap@acme.com;
        cc@acme.com"`). Addresses are trimmed, lowercased and de-duplicated.

        - Every address is validated; any malformed address rejects the whole
        request and nothing is written.

        - Writes the customer's **email** delivery method only. Portal and EDI
        delivery methods are never modified. If the customer has no email
        delivery method, one is created.

        - Only the recipient list changes. Other delivery settings (subject,
        schedule, delivery mode, conditional recipients) are preserved.

        - Delivery routing is written only when your organization has delivery
        routing switched on (Customer Settings → Delivery Routing). Then the
        customer's default routing rule is updated (or created) with the same
        recipients, and only the rule's **primary** target is replaced: any
        additional targets on that rule keep their own recipients and keep
        receiving routed invoices. The delivery method and the routing rule are
        written together: if the routing write fails, the delivery method change
        is rolled back. With routing off, routing rules are not read or changed
        and `routingRuleId` is `null` in the response.

        - An empty `emailAddresses` list is rejected unless
        `input.forceClearRecipients` is `true`. A forced clear clears the email
        delivery method's recipients only; routing rules require at least one
        recipient and are left unchanged (`routingRuleId` is `null` in the
        response), so routed invoice email can keep going to the existing
        routing targets.

        - `sourceSystem` matches case-insensitively; `sourceSystemId` must match
        exactly. The request is rejected if no customer, or more than one,
        matches.


        **Errors:** a rejected request still returns HTTP `200`. The body has no
        `setCustomerEmailDeliveryRecipientsBySourceSystemId` object and instead
        carries the error message (for example `Invalid email address(es):
        ...`). Check for the result object before reading it.
      parameters:
        - description: The customer's source system (case-insensitive)
          in: query
          name: sourceSystem
          schema:
            type: string
          required: true
        - description: The customer's id in the source system
          in: query
          name: sourceSystemId
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              properties:
                input:
                  $ref: '#/components/schemas/CustomerEmailDeliveryRecipientsInput'
                sourceSystem:
                  nullable: false
                  title: String
                  type: string
                sourceSystemId:
                  nullable: false
                  title: String
                  type: string
              type: object
              required:
                - input
        description: >-
          Query parameters can also be provided in the request body as a JSON
          object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  setCustomerEmailDeliveryRecipientsBySourceSystemId:
                    $ref: '#/components/schemas/CustomerEmailDeliveryRecipients'
                    nullable: false
                    properties:
                      customerId:
                        nullable: false
                        title: String
                        type: string
                      deliveryMethodCreated:
                        nullable: false
                        title: Boolean
                        type: boolean
                      deliveryMethodId:
                        nullable: false
                        title: String
                        type: string
                      emailAddresses:
                        items:
                          nullable: false
                          title: String
                          type: string
                        nullable: false
                        type: array
                      routingRuleCreated:
                        nullable: false
                        title: Boolean
                        type: boolean
                      routingRuleId:
                        nullable: true
                        title: String
                        type: string
                      type:
                        nullable: false
                        title: String
                        type: string
                    title: CustomerEmailDeliveryRecipients
                    type: object
                type: object
          description: Recipients updated
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
components:
  schemas:
    CustomerEmailDeliveryRecipientsInput:
      nullable: false
      properties:
        emailAddresses:
          items:
            nullable: false
            title: String
            type: string
          nullable: false
          type: array
          description: >-
            Full replacement list of invoice email recipients. Entries may be
            comma- or semicolon-separated. At most 100 addresses.
          example:
            - ap@acme.com
            - billing@acme.com; cc@acme.com
        forceClearRecipients:
          nullable: true
          title: Boolean
          type: boolean
          description: >-
            Set to `true` to allow an empty `emailAddresses` list to clear the
            recipients of an existing email delivery method. Clears only the
            email delivery method; any default routing rule and its targets are
            left unchanged, so routed email delivery may continue.
          default: false
      title: CustomerEmailDeliveryRecipientsInput
      type: object
      required:
        - emailAddresses
    CustomerEmailDeliveryRecipients:
      type: object
      properties:
        customerId:
          type: string
        deliveryMethodId:
          type: string
        type:
          description: Delivery method type; always `email` for this endpoint
          type: string
        emailAddresses:
          description: Recipients now stored on the email delivery method
          type: array
          items:
            type: string
        deliveryMethodCreated:
          description: >-
            `true` if the customer had no email delivery method and one was
            created
          type: boolean
        routingRuleId:
          description: >-
            Default delivery routing rule that was updated or created; `null` on
            a forced clear
          type: string
          nullable: true
        routingRuleCreated:
          type: boolean
      nullable: false
  responses:
    BadRequestError:
      description: >-
        Malformed or invalid request — missing required field, duplicate
        external key, wrong payload wrapper, or non-integer money. The body is a
        flat error object.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                description: Human-readable error message naming the problem.
              code:
                type: string
                description: >-
                  Machine-readable category when present (e.g.
                  `constraint-violation`, `bad-request`).
          example:
            error: >-
              Not-NULL violation. null value in column "shipment_id" of relation
              "shipments" violates not-null constraint
            code: constraint-violation
    UnauthorizedError:
      description: >-
        Missing, invalid, or revoked API key. The body is a flat authentication
        error object.
      content:
        application/json:
          schema:
            type: object
            required:
              - error
              - path
              - code
            properties:
              error:
                type: string
                description: Human-readable authentication error message.
              path:
                type: string
                description: Hasura error path (normally `$` for authentication failures).
              code:
                type: string
                description: Machine-readable category (`access-denied`).
          example:
            error: Authentication hook unauthorized this request
            path: $
            code: access-denied
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Your API key, sent in the `Authorization` header: `Authorization:
        YOUR_API_KEY`. A `Bearer ` prefix is also accepted (`Authorization:
        Bearer YOUR_API_KEY`). Keys are created in the Upwell dashboard (Account
        → API keys) and are scoped to one organization.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.