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

# Adjust inventory -- single or multi-item atomic (cycle count, shrinkage, revaluation)

> ATOMIC-CREATE (2026-05-12): accepts items[] for multi-line atomic adjustments OR
top-level product_id/quantity for single-item compat mode.
All items adjust in one DB transaction; any failure rolls back all items (no partial writes).
Positive or negative delta per item. Hard-blocks negative balance and zero-cost positives.
GL: DR/CR Inventory + DR/CR Suspense or Shrinkage via glPostInventoryAdjustment, fires per item in same transaction (Rule 21).
Connector: triggers async pushInventoryToMarketplaces.
Response: {object:inventory_adjustment_result, items:[{index,product_id,balance,transaction,gl_amount,journal_entry_id,consumed_layers}], summary} for items[]; single object for compat mode.
On failure: {error, code, hint, items_completed_before_failure} -- all items rolled back regardless of items_completed_before_failure.
migration:write scope: documents authorization for opening-balance loads. Hard-blocks still apply.




## OpenAPI

````yaml /openapi.yaml post /inventory/adjustments
openapi: 3.1.0
info:
  title: Arcus ERP Public API
  version: 1.0.0
  description: >
    Arcus ERP public REST API. Designed for external integrations and data
    migration.


    **Authentication.** Bearer token (API key) via the `Authorization` header.

    Format: `Authorization: Bearer ark_live_ent_<code>_<random>` (or
    `ark_test_*` for sandbox).

    API keys are issued per-entity in **Settings > Developers > API Keys**.


    **Entity scoping.** The entity is encoded in the API key prefix; routes are
    flat

    (e.g. `/v1/accounts`, `/v1/orders`, `/v1/products`). A small set of platform
    endpoints

    (migration, reconciliation, events, webhook endpoints, API keys) use the

    `/v1/entities/{entity_id}/...` form -- those are noted in their tags.


    **Key capabilities.**
      - Related-resource hydration via `?expand[]=` (see `x-arcus-expand` on each resource).
      - Cursor-based pagination (`starting_after` / `ending_before` / `limit`).
      - Idempotency via the `Idempotency-Key` header.
      - Webhook events for asynchronous notification.
      - Conditional requests / ETag for cache validation.
servers:
  - url: https://api.arcuserp.com/v1
    description: Arcus ERP API (accepts both live `ark_live_*` and test `ark_test_*` keys)
  - url: https://dev-api.arcuserp.com/v1
    description: >-
      Dev sandbox API (test-only data, accepts `ark_test_*` keys against dev
      RDS)
security: []
paths:
  /inventory/adjustments:
    post:
      tags:
        - Inventory
      summary: >-
        Adjust inventory -- single or multi-item atomic (cycle count, shrinkage,
        revaluation)
      description: >
        ATOMIC-CREATE (2026-05-12): accepts items[] for multi-line atomic
        adjustments OR

        top-level product_id/quantity for single-item compat mode.

        All items adjust in one DB transaction; any failure rolls back all items
        (no partial writes).

        Positive or negative delta per item. Hard-blocks negative balance and
        zero-cost positives.

        GL: DR/CR Inventory + DR/CR Suspense or Shrinkage via
        glPostInventoryAdjustment, fires per item in same transaction (Rule 21).

        Connector: triggers async pushInventoryToMarketplaces.

        Response: {object:inventory_adjustment_result,
        items:[{index,product_id,balance,transaction,gl_amount,journal_entry_id,consumed_layers}],
        summary} for items[]; single object for compat mode.

        On failure: {error, code, hint, items_completed_before_failure} -- all
        items rolled back regardless of items_completed_before_failure.

        migration:write scope: documents authorization for opening-balance
        loads. Hard-blocks still apply.
      operationId: postInventoryAdjustment
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  description: Multi-item atomic mode
                  required:
                    - location_id
                    - items
                  properties:
                    location_id:
                      type: string
                      format: uuid
                      description: Layer 4 -- required
                    reason:
                      type: string
                    items:
                      type: array
                      minItems: 1
                      items:
                        type: object
                        required:
                          - product_id
                          - quantity_delta
                        properties:
                          product_id:
                            type: string
                            format: uuid
                          quantity_delta:
                            type: integer
                            description: Signed delta (positive=add, negative=remove)
                          unit_cost:
                            type: number
                            description: Required for positive adjustments
                          notes:
                            type: string
                          allow_negative:
                            type: boolean
                            description: Requires inventory.allow_negative permission
                - type: object
                  description: Single-item compat mode
                  required:
                    - product_id
                    - location_id
                    - quantity
                  properties:
                    product_id:
                      type: string
                      format: uuid
                    location_id:
                      type: string
                      format: uuid
                      description: Layer 4 -- required
                    quantity:
                      type: integer
                      description: Signed delta (positive=add, negative=remove)
                    unit_cost:
                      type: number
                      description: Required for positive adjustments
                    reason:
                      type: string
                    notes:
                      type: string
                    allow_negative:
                      type: boolean
                      description: Requires inventory.allow_negative permission
            examples:
              cycle_count_multi:
                summary: Cycle count -- mixed positive and negative deltas (atomic)
                description: >
                  Adjust two SKUs in a single atomic transaction. Item 0 adds 3
                  units (positive

                  delta, unit_cost required to establish new FIFO layer). Item 1
                  removes 2 units

                  (negative delta, FIFO layers consumed automatically, unit_cost
                  not required).

                  On any failure both items roll back -- no partial writes.
                value:
                  location_id: 91aa7588-4dc7-4edd-b172-7de91f5e1f78
                  reason: cycle_count
                  memo: Monthly cycle count Q2 2026
                  items:
                    - product_id: 7f6f3e14-eaad-4c45-b922-209f6dc6d140
                      quantity_delta: 3
                      unit_cost: 12.5
                      notes: Count correction -- physical count higher than system
                    - product_id: ec9288c3-12b1-474f-bb09-b0b15bb7a8ff
                      quantity_delta: -2
                      notes: Shrinkage discovered during count
              shrinkage_single:
                summary: Single-item shrinkage write-down
                value:
                  product_id: 7f6f3e14-eaad-4c45-b922-209f6dc6d140
                  location_id: 91aa7588-4dc7-4edd-b172-7de91f5e1f78
                  quantity: -5
                  reason: shrinkage
                  notes: Damaged goods -- water exposure
      responses:
        '201':
          description: Adjustment applied
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    enum:
                      - inventory_adjustment_result
              examples:
                cycle_count_result:
                  summary: Cycle count adjustment result
                  value:
                    object: inventory_adjustment_result
                    items:
                      - index: 0
                        product_id: 7f6f3e14-eaad-4c45-b922-209f6dc6d140
                        location_id: 91aa7588-4dc7-4edd-b172-7de91f5e1f78
                        quantity_delta: 3
                        gl_amount: 37.5
                        journal_entry_id: c79ab8cf-b840-471f-bea9-6a24df80f550
                        balance:
                          on_hand: 13
                          allocated: 0
                          available: 13
                          total_value: '162.50'
                        transaction:
                          id: 10e06976-8096-48bc-bbbd-5fe71626f544
                          type: adjustment
                          quantity: 3
                          unit_price: '12.5000'
                          total_price: '37.50'
                          transaction_id: IVT-0000155
                        consumed_layers: []
                      - index: 1
                        product_id: ec9288c3-12b1-474f-bb09-b0b15bb7a8ff
                        location_id: 91aa7588-4dc7-4edd-b172-7de91f5e1f78
                        quantity_delta: -2
                        gl_amount: -17.5
                        journal_entry_id: a8c5c8c6-b0b0-4e63-918d-a247189735f3
                        balance:
                          on_hand: 3
                          allocated: 0
                          available: 3
                          total_value: '26.25'
                        transaction:
                          id: 93659e88-f3ba-4709-9798-388886820ea0
                          type: adjustment
                          quantity: -2
                          unit_price: '8.7500'
                          total_price: '17.50'
                          transaction_id: IVT-0000156
                        consumed_layers:
                          - layer_id: 3de7680e-fba2-444a-a204-7290cc6f08e1
                            qty_used: 2
                            qty_after: 3
                            unit_cost: 8.75
                            layer_cogs: 17.5
                    summary:
                      total_items: 2
                      total_gl_impact: 20
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/Error'
      security:
        - ApiKeyAuth: []
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: |
        Client-generated unique key for idempotent POST/PATCH/DELETE operations.
        Alias for the Idempotency parameter. Max 255 chars. On retry with the
        same key, the original response is returned without re-executing the
        operation. Keys expire after 24 hours.
      schema:
        type: string
        maxLength: 255
  responses:
    Error:
      description: Error response (400/401/403/404/409/422/429/500)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  schemas:
    ErrorEnvelope:
      type: object
      description: |
        Canonical error response envelope. All API errors use this shape.
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: Machine-readable error key
          example: not_found
        code:
          type: string
          description: Machine-readable error code (often same as error)
          example: not_found
        type:
          type: string
          enum:
            - validation_error
            - permission_error
            - not_found
            - conflict
            - rate_limit
            - internal
            - expand_error
            - not_implemented
          example: not_found
        hint:
          type: string
          description: Human-readable one-sentence explanation (English)
          example: >-
            The requested order does not exist or does not belong to this
            entity.
        param:
          type: string
          description: The parameter that caused the error, if applicable
          example: expand[0]
        required:
          type: string
          description: The scope required (only on insufficient_scope errors)
          example: accounts:read
        request_id:
          type: string
          description: >-
            Unique request ID for support tracing (maps to CloudWatch log
            stream)
          example: req_abc123
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: |
        API key issued per entity via Settings > Developers > API Keys.
        Each key carries scopes (e.g. orders:read, products:write).
        Bearer token format: Authorization: Bearer ark_live_ent_<code>_<random>
        Test keys use ark_test_ent_<code>_<random>. Both are issued per entity
        via Settings > Developers > API Keys.

````