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

# Update queue attributes

> The name, the kind, and `content_based_deduplication` are
immutable. The first two are the CRN and the delivery contract;
flipping the third would change how sends already accepted inside
the live deduplication window are interpreted.

Changing `kms_key_id` re-keys the queue. Messages already on it
keep the key they were sealed with, so they stay readable under
the old key until they drain — which is the point of rotating
away from a key you no longer trust.




## OpenAPI

````yaml /api-reference/specs/queue.yaml patch /v1/queues/{queue_id}
openapi: 3.0.3
info:
  title: Basaltic Queue API
  version: 1.0.0
  description: |
    Durable message queues with at-least-once delivery.

    **A receive is a lease, not a read.** `ReceiveMessage` hides the
    messages it returns for the queue's visibility timeout and hands back
    a *receipt handle*. The message comes back — to you or to another
    consumer — unless you delete it with that handle before the lease
    lapses. Everything else follows from this: a consumer that crashes
    mid-work loses nothing, and a message no consumer can process is
    caught by `receive_count` crossing the redrive threshold.

    **Receipt handles are per-lease, not per-message.** A new one is
    minted on every receive. Presenting a handle from a lease that has
    already lapsed fails with `QUEUE_RECEIPT_HANDLE_EXPIRED` rather than
    deleting a message that has since been handed to someone else — so a
    slow consumer finds out it was slow instead of silently destroying
    another's work.

    **Two kinds of queue, fixed at creation.** A *standard* queue
    delivers at least once with best-effort ordering and races
    consumers freely. A *FIFO* queue — whose name must end in `.fifo` —
    delivers strictly in order within a `message_group_id` and refuses
    to hand out a group's next message while an earlier one is still in
    flight; sends inside a five-minute window that repeat a
    `message_deduplication_id` collapse to one message. Ordering across
    groups is undefined, which is what lets groups run concurrently. The
    kind cannot be changed: a queue holding messages written under one
    set of rules cannot start honouring the other.

    **Long polling.** `wait_time_seconds` (up to 20) blocks the receive
    until a message arrives rather than returning empty immediately. It
    costs one request instead of the many an empty polling loop would
    make, and it returns as soon as a producer sends.

    **Message bodies are encrypted at rest.** Each queue has a data key
    that seals its messages; that key is itself wrapped by a platform key
    or, if you set `kms_key_id`, by your own. The unwrapped data key is
    cached for `kms_data_key_reuse_period_seconds` — so for up to that
    long after you disable your key, sends and receives on the queue keep
    working. Lower it to tighten that window at the cost of more KMS
    round-trips.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://queue.{region}.basaltic.sh
    description: Regional API endpoint
    variables:
      region:
        default: sa-saopaulo-1
        description: Region code
security:
  - SignatureAuth: []
tags:
  - name: Queues
    description: Queue lifecycle and attributes
  - name: Messages
    description: Sending, receiving, and acknowledging messages
paths:
  /v1/queues/{queue_id}:
    parameters:
      - $ref: '#/components/parameters/QueueId'
    patch:
      tags:
        - Queues
      summary: Update queue attributes
      description: |
        The name, the kind, and `content_based_deduplication` are
        immutable. The first two are the CRN and the delivery contract;
        flipping the third would change how sends already accepted inside
        the live deduplication window are interpreted.

        Changing `kms_key_id` re-keys the queue. Messages already on it
        keep the key they were sealed with, so they stay readable under
        the old key until they drain — which is the point of rotating
        away from a key you no longer trust.
      operationId: updateQueue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateQueueRequest'
      responses:
        '200':
          description: Queue updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QueueResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    QueueId:
      name: queue_id
      in: path
      required: true
      schema:
        type: string
        format: uuid
        example: a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
  schemas:
    UpdateQueueRequest:
      type: object
      properties:
        visibility_timeout_seconds:
          type: integer
          minimum: 0
          maximum: 43200
          example: 60
        message_retention_seconds:
          type: integer
          minimum: 60
          maximum: 1209600
          example: 345600
        max_message_bytes:
          type: integer
          minimum: 1024
          maximum: 262144
          example: 262144
        delay_seconds:
          type: integer
          minimum: 0
          maximum: 900
          example: 0
        receive_wait_time_seconds:
          type: integer
          minimum: 0
          maximum: 20
          example: 20
        kms_data_key_reuse_period_seconds:
          type: integer
          minimum: 60
          maximum: 86400
          example: 300
        redrive_policy:
          $ref: '#/components/schemas/RedrivePolicy'
        clear_redrive_policy:
          type: boolean
          description: |
            Removes the redrive policy, disarming poison-pill handling.
            Explicit rather than inferred from a null `redrive_policy`,
            because an absent field and a null one are indistinguishable
            after decoding and they mean opposite things.
          example: false
        kms_key_id:
          type: string
          format: uuid
          description: Re-key the queue. Existing messages keep the key that sealed them.
          example: d4e5f6a7-8b9c-4d0e-9f1a-2b3c4d5e6f70
        clear_kms_key:
          type: boolean
          description: >-
            Move the queue back to the platform key. Explicit for the same
            reason as clear_redrive_policy.
          example: false
        tags:
          $ref: '#/components/schemas/Tags'
    QueueResponse:
      type: object
      required:
        - queue
      properties:
        queue:
          $ref: '#/components/schemas/Queue'
    RedrivePolicy:
      type: object
      description: |
        Quarantines a message that has been leased and abandoned too many
        times. Once `receive_count` reaches `max_receive_count` the
        message stops being delivered and is moved to the dead-letter
        queue, which must be the same kind as this one.
      required:
        - dead_letter_queue_id
        - max_receive_count
      properties:
        dead_letter_queue_id:
          type: string
          format: uuid
          example: b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e
        max_receive_count:
          type: integer
          minimum: 1
          maximum: 1000
          example: 5
    Tags:
      type: object
      additionalProperties:
        type: string
      example:
        environment: production
        team: backend
    Queue:
      type: object
      required:
        - id
        - crn
        - name
        - kind
        - attributes
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
          example: a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
        crn:
          type: string
          example: crn:queue:sa-saopaulo-1:my-account:queue/orders
        name:
          type: string
          description: Unique within the calling account. Immutable.
          example: orders
        kind:
          type: string
          enum:
            - standard
            - fifo
          description: Derived from the name and immutable.
          example: standard
        attributes:
          $ref: '#/components/schemas/QueueAttributes'
        redrive_policy:
          $ref: '#/components/schemas/RedrivePolicy'
        content_based_deduplication:
          type: boolean
          description: >-
            FIFO only. Derives a deduplication id from a hash of the body when
            the sender supplies none.
          example: false
        kms_key_id:
          type: string
          format: uuid
          nullable: true
          description: >-
            Customer-managed key wrapping this queue's data key. Absent means
            the platform key.
          example: d4e5f6a7-8b9c-4d0e-9f1a-2b3c4d5e6f70
        tags:
          $ref: '#/components/schemas/Tags'
        depth:
          $ref: '#/components/schemas/QueueDepth'
        created_at:
          type: string
          format: date-time
          example: '2026-01-15T09:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-01-18T11:45:00Z'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: Error code identifying the type of error
              example: INVALID_INPUT
            message:
              type: string
              description: Human-readable error message
              example: Invalid request parameters
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
    QueueAttributes:
      type: object
      description: A queue's tunable behaviour. All durations are whole seconds.
      properties:
        visibility_timeout_seconds:
          type: integer
          minimum: 0
          maximum: 43200
          description: >-
            How long a received message stays invisible before redelivery. 0
            redelivers immediately.
          example: 30
        message_retention_seconds:
          type: integer
          minimum: 60
          maximum: 1209600
          description: How long an undeleted message survives before it is discarded.
          example: 345600
        max_message_bytes:
          type: integer
          minimum: 1024
          maximum: 262144
          description: >-
            Largest accepted message. Attributes count against this alongside
            the body.
          example: 262144
        delay_seconds:
          type: integer
          minimum: 0
          maximum: 900
          description: >-
            Default delay applied to every send that does not override it. Not
            supported on FIFO queues.
          example: 0
        receive_wait_time_seconds:
          type: integer
          minimum: 0
          maximum: 20
          description: Default long-poll window for a receive that does not override it.
          example: 0
        kms_data_key_reuse_period_seconds:
          type: integer
          minimum: 60
          maximum: 86400
          description: |
            How long an unwrapped data key is cached. Sends and receives
            keep working for up to this long after the wrapping key is
            disabled; lower it to tighten that window at the cost of more
            KMS round-trips.
          example: 300
    QueueDepth:
      type: object
      description: |
        Approximate message census. Approximate by construction: an exact
        count of a deep queue is a sequential scan, and the number is
        stale the moment it is returned. Counts are capped at 10000 —
        `counts_capped` reports that at least one is a floor rather than
        an exact figure.
      properties:
        approximate_available:
          type: integer
          example: 42
        approximate_in_flight:
          type: integer
          example: 3
        approximate_delayed:
          type: integer
          example: 0
        counts_capped:
          type: boolean
          example: false
  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_INPUT
              message: Invalid request parameters
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Unauthorized:
      description: Authentication required or token invalid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: UNAUTHORIZED
              message: Authentication required
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ACCESS_DENIED
              message: You don't have permission to perform this action
              request_id: 550e8400-e29b-41d4-a716-446655440000
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: Resource not found
              request_id: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    SignatureAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >
        Request signing with an access key issued to a service account. An

        HMAC-SHA256 over a canonical form of the request, close to AWS SigV4.

        The `basaltic` CLI signs for you.


        Send `Authorization`, `X-Date` (UTC, `YYYYMMDDTHHMMSSZ`) and `X-Nonce`

        (random per request); add `X-Content-Sha256` to bind a body, and

        `X-Amz-Security-Token` when using temporary credentials.


        ```

        Authorization: BASALTIC-HMAC-SHA256
        Credential=<access_key_id>/<date>/<region>/basaltic/basaltic_request,
        SignedHeaders=host;x-date;x-nonce, Signature=<hex>

        ```


        `<region>` is the region code you are calling, or `global` for the
        global

        services. A signature is valid for 5 minutes from `X-Date`, and mutating

        requests are replay-guarded on the nonce.


        **Full signing procedure, including a working implementation:**

        https://docs.basaltic.sh/authentication


        ## Rate limits

        There is no global request budget. A limit applies only where an

        operation documents a `429`, and that operation says what it counts.

        Those responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining`,

        `X-RateLimit-Reset` and, on a `429`, `Retry-After` — read them rather

        than hard-coding a number. Retrying before `Retry-After` is refused and

        extends the window. Everything else is bounded by quota, not by request

        rate.

````