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

# Add household member

> Moves the donor from an existing household when necessary and atomically refreshes both households. Cross-organization references are rejected.



## OpenAPI

````yaml /openapi.json post /api/v1/households/{id}/members
openapi: 3.0.3
info:
  title: Grain API
  description: >-
    Church accounting and donor management API. Use an organization API key for
    server automation or OAuth 2.1 (Sign in with Grain) for applications acting
    on behalf of users. OAuth requests require X-Organization-Id; API keys infer
    it.
  version: 1.1.0
servers:
  - url: https://api.grainledger.com
    description: API Server
security:
  - ApiKeyAuth: []
  - GrainOAuth2: []
  - BearerAuth: []
tags:
  - name: Transactions
    description: Bank transactions and reconciliation
  - name: Bills
    description: Vendor bills from creation through payment
  - name: Donors
    description: Donor records and household relationships
  - name: Contributions
    description: Giving records with fund assignment and settlement
  - name: Giving Batches
    description: Contribution groups with derived totals and lifecycle state
  - name: Settlements
    description: Provider deposits with recorded and linked-contribution totals
  - name: Pledges
    description: Pledge campaigns and fulfillment tracking
  - name: Pledge Card Imports
    description: Submit structured pledge card data for review
  - name: Households
    description: Household groupings and primary contacts
paths:
  /api/v1/households/{id}/members:
    post:
      tags:
        - Households
      summary: Add household member
      description: >-
        Moves the donor from an existing household when necessary and atomically
        refreshes both households. Cross-organization references are rejected.
      parameters:
        - $ref: '#/components/parameters/OrganizationId'
        - $ref: '#/components/parameters/PathId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HouseholdMemberWrite'
      responses:
        '201':
          description: Updated household
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Household'
        '400':
          description: Bad request (missing header or invalid input)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized (missing or invalid Bearer token)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden (no access to organization or action)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            Conflict (duplicate, cross-resource ownership conflict, concurrent
            change, or accounting-frozen resource)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  parameters:
    OrganizationId:
      name: X-Organization-Id
      in: header
      required: false
      schema:
        type: string
      description: >-
        Required with OAuth access tokens. Optional with organization API keys;
        if supplied, it must match the key's organization.
      example: cm123abc456def
    PathId:
      name: id
      in: path
      required: true
      schema:
        type: string
      description: Resource ID
      example: cm456def789ghi
  schemas:
    HouseholdMemberWrite:
      type: object
      additionalProperties: false
      required:
        - donorId
      properties:
        donorId:
          type: string
        position:
          type: string
          nullable: true
          enum:
            - PRIMARY
            - SPOUSE
            - CHILD
            - OTHER
        isPrimaryContact:
          type: boolean
    Household:
      type: object
      description: >-
        Household detail with a compact member collection, normalized external
        IDs, primary contact, and live giving aggregates.
      properties:
        id:
          type: string
        name:
          type: string
        primaryContactId:
          type: string
          nullable: true
        primaryContact:
          $ref: '#/components/schemas/DonorSummary'
          nullable: true
        externalIds:
          type: array
          items:
            $ref: '#/components/schemas/ExternalId'
        members:
          type: array
          items:
            $ref: '#/components/schemas/DonorSummary'
        aggregates:
          type: object
          properties:
            memberCount:
              type: integer
            lifetimeGiving:
              type: number
            lastGiftDate:
              type: string
              format: date-time
              nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Error:
      type: object
      description: >-
        Every error response is valid JSON with this shape. The HTTP status code
        carries the outcome; `code` is a stable machine-readable form of it.
      required:
        - code
        - message
      properties:
        code:
          type: string
          enum:
            - bad_request
            - unauthorized
            - forbidden
            - not_found
            - conflict
            - unprocessable_entity
            - payload_too_large
            - rate_limited
            - internal_server_error
          example: forbidden
        message:
          type: string
          example: You do not have access to this organization.
        error:
          type: string
          deprecated: true
          description: Deprecated alias for `message`. Read `message` instead.
          example: You do not have access to this organization.
    DonorSummary:
      type: object
      description: >-
        Compact donor identity, household, membership, and giving summary used
        in list and relationship responses.
      properties:
        id:
          type: string
        firstName:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        organizationName:
          type: string
          nullable: true
        donorType:
          type: string
          enum:
            - INDIVIDUAL
            - HOUSEHOLD
            - ORGANIZATION
            - DAF_CUSTODIAN
            - FOUNDATION
            - ESTATE
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        householdRef:
          type: string
          nullable: true
        householdName:
          type: string
          nullable: true
        householdPosition:
          type: string
          nullable: true
          enum:
            - PRIMARY
            - SPOUSE
            - CHILD
            - OTHER
        isPrimaryContact:
          type: boolean
        membershipStatus:
          type: string
          nullable: true
          enum:
            - VISITOR
            - REGULAR_ATTENDER
            - MEMBER
            - INACTIVE
            - FORMER
        isActive:
          type: boolean
        totalGiving:
          type: number
        givingTrend:
          type: number
          nullable: true
        createdAt:
          type: string
          format: date-time
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
    ExternalId:
      type: object
      required:
        - platform
        - externalId
      properties:
        platform:
          type: string
        externalId:
          type: string
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: grain_live_… or grain_test_…
      description: >-
        Organization API key created in Grain Settings → API. The key determines
        the organization and is limited to its assigned resource scopes. Write
        scopes imply the corresponding read scope.
    GrainOAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://auth.grainledger.com/auth/v1/oauth/authorize
          tokenUrl: https://auth.grainledger.com/auth/v1/oauth/token
          scopes:
            openid: OpenID Connect
            email: Email address
            profile: Profile information
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: OAuth access token (JWT)

````