Skip to content

[Feature New API] Add a bulk UPSERT Endpoint for Custom Values #102

Description

@cbnsndwch

🌟 Describe the Feature

As a developer building integrations for the GHL API
I would like there to be an endpoint that allows creating or updating custom values for a location in bulk
So that I can atomically create or update location custom values without overconsuming API request quota or incurring delays due to rate limits and exponential backoff

🚀 Justification

We have a use case where we help agency owners set up custom values in bulk to power snapshots and/or workflows.

We hit rate limits in some cases where we need to populate a large number of CVs in a short interval. We do perform rate limiting and exponential back off on our side, however this is suboptimal:

  • causes poor UX - users expect the operation to be atomic but the rate limits force it to be eventually consistent at best
  • overconsumes API request quota - one request per custom value

📝 Suggestions

Desired Acceptance Criteria

  • the endpoint shall be separate from the existing CREATE and UPDATE endpoints so as to not break existing contracts
  • caller shall pass an array of CustomValuesDTO as a JSON array in the request body
  • server shall find existing custom values that match items from the request by name and update their values
  • server shall create new Custom Values where no item exists that matches the name of an item in the request

Desired API Spec

openapi: 3.0.0
info:
  title: Sub-Account (Formerly location) API
  description: Documentation for Sub-Account (Formerly location) API
  version: '1.0'
tags:
  - name: Custom Value
    description: Documentation for Sub-Account (Formerly location) API
servers:
  - url: https://services.leadconnectorhq.com
components:
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      name: Authorization
      description: Use the Access Token generated with user type as Sub-Account (OR) Private Integration Token of Sub-Account.
  schemas:
    # error response schemas
    BadRequestDTO:
      type: object
      properties:
        statusCode:
          type: number
          example: 400
        message:
          type: string
          example: Bad Request
    UnauthorizedDTO:
      type: object
      properties:
        statusCode:
          type: number
          example: 401
        message:
          type: string
          example: 'Invalid token: access token is invalid'
        error:
          type: string
          example: Unauthorized
    UnprocessableDTO:
      type: object
      properties:
        statusCode:
          type: number
          example: 422
        message:
          example:
            - Unprocessable Entity
          type: array
          items:
            type: string
        error:
          type: string
          example: Unprocessable Entity
    # success response schemas
    CustomValueSchema:
      type: object
      properties:
        id:
          type: string
          example: rWQ709Pb62syqGLceg1x
        name:
          type: string
          example: Custom Field
        fieldKey:
          type: string
          example: '{{ custom_values.custom_field }}'
        value:
          type: string
          example: Value
        locationId:
          type: string
          example: rWQ709Pb6dasyqGLceg1x
    CustomValuesListSuccessfulResponseDto:
      type: object
      properties:
        customValues:
          type: array
          items:
            $ref: '#/components/schemas/CustomValueSchema'
    CustomValuesDTO:
      type: object
      properties:
        name:
          type: string
          example: Custom Value Name
        value:
          type: string
          example: Value
      required:
        - name
        - value
    CustomValuesListDTO:
      type: array
      items:
        $ref: '#/components/schemas/CustomValuesDTO'
      example:
        - name: Custom Value 1 Name
          value: Custom Value 1 Content
        - name: Custom Value 2 Name
          value: Custom Value 2 Content
paths:
  /locations/{locationId}/customValues/bulk:
    post:
      operationId: bulk-upsert-custom-value
      summary: Bulk Upsert Custom Values
      description: Create or update multiple custom values for a location
      parameters:
        - name: Version
          in: header
          description: API Version
          required: true
          schema:
            type: string
            enum:
              - '2021-07-28'
        - name: locationId
          required: true
          in: path
          description: Location Id
          example: ve9EPM428h8vShlRW1KT
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomValuesListDTO'
      responses:
        '201':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomValuesListSuccessfulResponseDto'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestDTO'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedDTO'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableDTO'
      tags:
        - Custom Value
      security:
        - bearer: []

Product Area

locations

🧠 Additional Context

seems to already be a few bulk API endpoints

Image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions