> ## 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.

# Create or replace a group's inline policy

<Info>
  Requires the IAM action **`workspace:PutInlinePolicy`**. See [WORKSPACE permissions](/workspace/permissions) for the full list, what each one covers, and an example policy.
</Info>


## OpenAPI

````yaml /api-reference/specs/workspace.yaml put /v1/groups/{group_id}/inline-policies/{policy_name}
openapi: 3.0.3
info:
  title: Basaltic Workspace API
  version: 1.0.0
  description: >
    Organization management: organizations, accounts, human users, users-only
    groups, and organization policies. Account IAM identities may receive
    explicitly delegated organization policies through this API. Personal
    authentication remains at the IAM endpoint.


    Organization resources are global and are resolved in the authenticated
    organization. Canonical CRNs are
    crn:workspace:::organization/<organization-uuid>/<type>/<name-or-uuid>.
    Organization policies are separate from account policies; shared system
    policies use crn:workspace:::policy/<name>.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://workspace.basaltic.sh
    description: Global API endpoint
security:
  - BearerAuth: []
paths:
  /v1/groups/{group_id}/inline-policies/{policy_name}:
    parameters:
      - name: group_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-1234-567890abcdef
      - name: policy_name
        description: >-
          Inline policy name. UUID spellings and the literal crn: prefix are
          reserved and cannot be used when creating a policy.
        in: path
        required: true
        schema:
          type: string
          example: S3BucketAccess
    put:
      tags:
        - Workspace
      summary: Create or replace a group's inline policy
      operationId: putGroupInlinePolicy
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PutInlinePolicyRequest'
      responses:
        '200':
          description: Inline policy stored
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InlinePolicyResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
components:
  schemas:
    PutInlinePolicyRequest:
      type: object
      required:
        - document
      properties:
        document:
          $ref: '#/components/schemas/PolicyDocument'
    InlinePolicyResponse:
      type: object
      properties:
        inline_policy:
          $ref: '#/components/schemas/InlinePolicy'
    PolicyDocument:
      type: object
      description: IAM-style policy document
      required:
        - version
        - statements
      properties:
        version:
          type: string
          enum:
            - '2024-01-01'
          example: '2024-01-01'
        statements:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PolicyStatement'
    InlinePolicy:
      type: object
      required:
        - crn
      properties:
        crn:
          type: string
          description: >-
            Canonical principal-scoped inline policy identity; named principals
            use their immutable name, users use UUID.
          example: crn:workspace:::role/deployer/inline-policy/read-storage
        id:
          type: string
          format: uuid
          example: d4e5f6a7-b8c9-0123-4567-890abcdef123
        principal_id:
          type: string
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
        principal_type:
          type: string
          enum:
            - user
            - group
          example: user
        name:
          description: >-
            Resource names must not start with the literal crn: prefix or be
            UUIDs (canonical, compact, braced, or urn:uuid: forms, in either
            case).
          type: string
          example: S3BucketAccess
        document:
          $ref: '#/components/schemas/PolicyDocument'
        created_at:
          type: string
          format: date-time
          example: '2026-01-15T09:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-01-16T14:20: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
    PolicyStatement:
      type: object
      description: >
        A single statement. The action set is named either positively
        (`actions`)

        or by exclusion (`not_actions`), and the resource set likewise

        (`resources` / `not_resources`) — exactly one of each pair. A statement

        that sets both sides of a pair, or neither, is rejected with

        `INVALID_INPUT` when the document is saved.
      required:
        - effect
      allOf:
        - oneOf:
            - required:
                - actions
            - required:
                - not_actions
        - oneOf:
            - required:
                - resources
            - required:
                - not_resources
      properties:
        sid:
          type: string
          description: Statement identifier
          example: ReadOrganizationUsers
        effect:
          type: string
          enum:
            - allow
            - deny
          example: allow
        actions:
          type: array
          minItems: 1
          items:
            type: string
          description: Actions in service:action format
          example:
            - workspace:GetUser
            - workspace:ListUsers
        not_actions:
          type: array
          minItems: 1
          items:
            type: string
          description: >
            The statement covers every action *except* these. Pairs naturally
            with

            `effect: deny` to carve a hole out of a broad allow; with

            `effect: allow` it grants everything the listed patterns don't name,

            including actions added by future services.
          example:
            - workspace:*
        resources:
          type: array
          minItems: 1
          items:
            type: string
          description: Resource identifiers or patterns
          example:
            - >-
              crn:workspace:::organization/550e8400-e29b-41d4-a716-446655440000/user/*
        not_resources:
          type: array
          minItems: 1
          items:
            type: string
          description: >
            The statement covers every resource *except* these. Same trade-off
            as

            `not_actions`: with `effect: allow` it reaches resources that do not

            exist yet.
          example:
            - >-
              crn:workspace:::organization/550e8400-e29b-41d4-a716-446655440000/user/*
        conditions:
          type: array
          description: Optional conditions for the statement
          items:
            $ref: '#/components/schemas/PolicyCondition'
    PolicyCondition:
      type: object
      description: A condition that must be satisfied for the statement to apply
      required:
        - operator
        - key
        - values
      properties:
        operator:
          type: string
          enum:
            - equals
            - not_equals
            - starts_with
            - ends_with
            - contains
            - in
            - not_in
            - greater_than
            - less_than
            - greater_than_or_equals
            - less_than_or_equals
            - exists
            - not_exists
            - ip_address
            - not_ip_address
          description: The comparison operator
          example: equals
        key:
          type: string
          description: The condition key to evaluate
          example: s3:prefix
        values:
          type: array
          items:
            type: string
          description: Values to compare against
          example:
            - home/
            - shared/
        set_operator:
          type: string
          enum:
            - for_all_values
            - for_any_value
          description: >
            Evaluates `operator` against a multi-valued context key (a set, such
            as

            `basalt:TagKeys` — the tag keys a request carries) rather than a
            single

            value. Omit for an ordinary single-valued condition.


            - `for_all_values` — holds when every member of the request set
              satisfies `operator`. An absent or empty set holds vacuously, so a
              request carrying no tags is not fenced by a tag-key restriction.
            - `for_any_value` — holds when at least one member does. An absent
            or
              empty set does not hold.
          example: for_all_values
  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
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: An internal error occurred
              request_id: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An OAuth 2.0 bearer token, sent as `Authorization: Bearer <token>`.
        This is the recommended way to authenticate.

        Get one by exchanging a service account's access key pair at
        `POST /v1/oauth/token` with `grant_type=client_credentials`. It is the
        standard client-credentials grant, so any OAuth-aware library will
        obtain and refresh it for you.

        ```
        curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
          https://iam.basaltic.sh/v1/oauth/token
        ```

        Tokens last an hour by default. The same access key pair is separately
        your AWS SigV4 credential for the S3-compatible object endpoint, which
        speaks nothing else.

````