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

# Update service

> Update a service. Passing `category_id` moves the service to that
category; omitting it leaves the service where it is.




## OpenAPI

````yaml put /services/{id}
openapi: 3.1.0
info:
  title: CookieChimp API
  description: |
    API for CookieChimp.com.

    ## Request bodies

    Resource endpoints expect the resource wrapped under its own key, e.g.
    `{"category": {"name": "Analytics"}}` rather than a bare object.
    `PUT /password` wraps in `user`. Two endpoints take their body unwrapped:
    `POST /auth`, which takes `email` and `password` at the top level, and
    `POST /consent-banners/from-template`, which takes `jurisdiction_id` —
    a selector for which template to build from, not an attribute of the
    banner it creates.

    ## Response envelopes

    Listing endpoints — including `GET /groups` and `GET /accounts` — return
    `{"pagination": {...}, "data": [...]}`. `GET /banner-templates` is the
    exception: it returns `{"data": [...]}` with no pagination, being a fixed
    catalogue rather than a collection of the account's records.
    Most single-resource endpoints
    return `{"data": {...}}`; a single group or account is returned unwrapped.
    Resource-deletion endpoints return `{"message": "..."}`; `DELETE /auth`
    returns an empty object.
  version: 1.2.0
servers:
  - url: https://cookiechimp.com/api/v1
security:
  - authorization: []
paths:
  /services/{id}:
    put:
      tags:
        - Services
      summary: Update service
      description: |
        Update a service. Passing `category_id` moves the service to that
        category; omitting it leaves the service where it is.
      operationId: updateService
      parameters:
        - $ref: '#/components/parameters/account_id'
        - $ref: '#/components/parameters/id'
      requestBody:
        description: Service to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SiteServiceUpdateRequest'
      responses:
        '200':
          description: Updated service
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SiteServiceResponse'
        '400':
          $ref: '#/components/responses/AmbiguousAccount'
        '401':
          $ref: '#/components/responses/AccountTokenRequired'
        '403':
          $ref: '#/components/responses/AccountAdminRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    account_id:
      name: account_id
      in: query
      description: |
        Which account to act on, as the account's API id. Only meaningful for a
        user API key, which may reach several accounts — an account key already
        identifies exactly one and ignores this.

        Accepted by the endpoints that declare it; others act on the account the
        key resolves to on its own.

        Optional for reads, where it narrows the request to that account.
        Required for writes that declare it when the key can reach more than one
        account: without it the request would act on an account it picked rather
        than one you named, so it is refused with a `400`.
      required: false
      schema:
        type: string
    id:
      name: id
      in: path
      description: ID of the resource
      required: true
      schema:
        type: string
  schemas:
    SiteServiceUpdateRequest:
      type: object
      description: |
        Every field is optional; anything omitted keeps its current value.
        Supplying `category_id` moves the service to that category.
      properties:
        site_service:
          $ref: '#/components/schemas/SiteServiceWrite'
      required:
        - site_service
      example:
        site_service:
          name: Google Analytics 4
          auto_block: false
    SiteServiceResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/SiteService'
    SiteServiceWrite:
      description: |
        Everything a service accepts on update, including its translations.
      allOf:
        - $ref: '#/components/schemas/SiteServiceSettings'
        - type: object
          properties:
            site_service_translations_attributes:
              type: array
              description: >
                Create, update or discard the localized copy a visitor reads
                when the

                banner runs in another language. Send an entry without an `id`
                to add

                a translation, with the `id` the response gave you to change
                one, and

                with `discarded_at` set to remove one.


                Not accepted when creating a service — add them by updating it,
                which

                is where the account's language entitlement is enforced.
              items:
                type: object
                description: >
                  An entry without an `id` creates a translation and must name
                  its

                  `language_code`; an entry with one may send only the fields it

                  changes.
                anyOf:
                  - required:
                      - id
                  - required:
                      - language_code
                properties:
                  id:
                    type: string
                    description: >
                      The translation's ID, as returned in `translations`. Omit
                      it to

                      add a new translation.
                  language_code:
                    type: string
                    description: |
                      The language this copy is for. Cannot be the service's own
                      `default_language`, and each language may appear once.
                  description:
                    type:
                      - string
                      - 'null'
                  additional_info:
                    type:
                      - string
                      - 'null'
                  discarded_at:
                    type:
                      - string
                      - 'null'
                    format: date-time
                    description: Set to remove this translation
    SiteService:
      type: object
      properties:
        id:
          type: string
          readOnly: true
        name:
          type: string
        description:
          type:
            - string
            - 'null'
        processing_company:
          type:
            - string
            - 'null'
        privacy_policy_url:
          type:
            - string
            - 'null'
        additional_info:
          type:
            - string
            - 'null'
        accepted_by_default:
          type: boolean
        enabled:
          type: boolean
        auto_block:
          type: boolean
        auto_block_domains:
          type: array
          items:
            type: string
          description: Domains the widget blocks for this service before consent
        default_language:
          type:
            - string
            - 'null'
        category:
          type: object
          description: The category this service is filed under
          properties:
            id:
              type:
                - string
                - 'null'
            name:
              type:
                - string
                - 'null'
        translations:
          type: array
          description: >
            The localized copy for this service, one entry per language, with
            the

            IDs `site_service_translations_attributes` expects back. Discarded

            translations are not returned.
          items:
            type: object
            properties:
              id:
                type: string
              language_code:
                type: string
              description:
                type:
                  - string
                  - 'null'
              additional_info:
                type:
                  - string
                  - 'null'
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true
      example:
        id: svc1
        name: Google Analytics
        description: Measures how visitors use the site.
        processing_company: Google LLC
        privacy_policy_url: https://policies.google.com/privacy
        additional_info: null
        accepted_by_default: false
        enabled: true
        auto_block: true
        auto_block_domains:
          - google-analytics.com
        default_language: en
        category:
          id: cat1
          name: Analytics
        translations:
          - id: svct1
            language_code: de
            description: Misst, wie Besucher die Website nutzen.
            additional_info: null
        created_at: '2023-03-01T09:00:00Z'
        updated_at: '2023-03-23T12:34:56Z'
    Error:
      type: object
      description: |
        The standard error envelope, used for authentication, authorization,
        pagination and not-found errors.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              code:
                type: integer
              message:
                type: string
      example:
        errors:
          - code: 401
            message: Invalid API Key
    ValidationError:
      type: object
      description: |
        Returned when a create or update fails validation. Each entry carries a
        single human-readable `error` string.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              error:
                type: string
      example:
        errors:
          - error: Name can't be blank
    SiteServiceSettings:
      type: object
      properties:
        name:
          type: string
          description: Name of the service, shown to visitors
        category_id:
          type: string
          description: |
            ID of the category the service belongs to. Required on create;
            on update, supplying it moves the service to that category.
        description:
          type: string
          description: Description shown to visitors
        processing_company:
          type: string
          description: Company that processes data through this service
        privacy_policy_url:
          type: string
        additional_info:
          type: string
        accepted_by_default:
          type: boolean
          description: Whether the service is pre-accepted in the banner
        enabled:
          type: boolean
          description: Whether the service is active on the account
        auto_block:
          type: boolean
          description: Whether the widget blocks this service's scripts before consent
        auto_block_domains_input:
          type: string
          description: |
            Domains to auto-block, separated by commas or newlines. Parsed into
            the `auto_block_domains` list on save.
  responses:
    AmbiguousAccount:
      description: |
        A user API key that can reach more than one account attempted a write
        without saying which account it meant. Pass `account_id` (the account's
        API id) as a query parameter. Account keys are never ambiguous.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            errors:
              - code: 400
                message: >-
                  Specify account_id when the API key can access more than one
                  account
    AccountTokenRequired:
      description: |
        Missing or invalid API token, or a token that does not resolve to an
        account. Account-scoped endpoints accept an account token, or a user
        token whose user belongs to an account; partner tokens are rejected.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            errors:
              - code: 401
                message: API key must belong to an account
    AccountAdminRequired:
      description: |
        The token resolved to a user who is not an admin of this account.
        Configuration changes are admin-only, mirroring the dashboard — a group
        admin qualifies even without a direct membership, since a group role
        supersedes one. Account tokens carry the account's own authority and
        never see this; reads are unaffected.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            errors:
              - code: 403
                message: User must be an admin of this account
    NotFound:
      description: The record does not exist, or does not belong to the caller
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            errors:
              - code: 404
                message: Record not found
    ValidationError:
      description: The record could not be saved
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
    RateLimited:
      description: |
        Too many requests. The general limit is 300 requests per 5 minutes per
        API token; the auth endpoints are throttled more tightly per IP.
      headers:
        Retry-After:
          description: Seconds until the current rate-limit window resets
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            errors:
              - code: 429
                message: Too many requests. Please retry later.
  securitySchemes:
    authorization:
      type: http
      scheme: bearer
      description: API token obtained from the login endpoint or the dashboard

````