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

# Submit elections

> For partners that run benefits administration (`benefitsAdmin: partner`). Sends each employee's final election. The group needs its enrollment first (`409 conflict` otherwise). Valid rows are applied and invalid rows come back in `errors` by `index`; the response is `400` when no row is valid. Prescience marks the elections on the group's census, records each coverage effective date, and emails each enrolled member a login (not in test mode). For a partner that runs benefits administration, a `deductions.changed` webhook follows with each submitted member's `coverage` and `deduction`. Needs the `elections` capability, which broker keys have by default; other keys return `403 forbidden`. Rate limit: 20 writes per minute, shared with census writes.



## OpenAPI

````yaml /api-reference/openapi.json post /groups/{groupId}/elections
openapi: 3.1.0
info:
  title: Prescience Partner API
  version: 1.1.0
  description: >-
    Create employer groups, submit census records, generate preliminary
    market-rate quotes, create iframe sessions, create enrollments, and read
    aggregate account data.


    Money is always integer cents. Dates are `YYYY-MM-DD`; timestamps are ISO
    8601 UTC. Final pricing, eligibility, network availability, and plan
    documents are confirmed during underwriting and onboarding. A BAA and data
    processing agreement are executed before live mode is enabled.
  contact:
    name: Prescience partner engineering
    email: partners@getprescience.com
servers:
  - url: https://www.getprescience.com/api/partner/v1
    description: >-
      Production. Test and live traffic share this host; mode comes from your
      API key.
security:
  - bearerAuth: []
tags:
  - name: Health
    description: Connectivity and key checks.
  - name: Plans
    description: Static plan metadata.
  - name: Groups
    description: 'Employer groups: the root resource of every integration.'
  - name: Census
    description: Pre-enrollment census intake and ongoing member sync.
  - name: Quotes
    description: >-
      Preliminary quotes built from the stored census and current local
      market-plan snapshot.
  - name: Enrollments
    description: Plan selection and employer provisioning.
  - name: Account
    description: Aggregate, de-identified employer account data.
  - name: Brokers
    description: >-
      Quoting for brokers, the MCP server, and elections for partner-run
      enrollment.
  - name: Webhooks
    description: Signed event delivery (standard-webhooks scheme).
paths:
  /groups/{groupId}/elections:
    post:
      tags:
        - Brokers
      summary: Submit elections
      description: >-
        For partners that run benefits administration (`benefitsAdmin:
        partner`). Sends each employee's final election. The group needs its
        enrollment first (`409 conflict` otherwise). Valid rows are applied and
        invalid rows come back in `errors` by `index`; the response is `400`
        when no row is valid. Prescience marks the elections on the group's
        census, records each coverage effective date, and emails each enrolled
        member a login (not in test mode). For a partner that runs benefits
        administration, a `deductions.changed` webhook follows with each
        submitted member's `coverage` and `deduction`. Needs the `elections`
        capability, which broker keys have by default; other keys return `403
        forbidden`. Rate limit: 20 writes per minute, shared with census writes.
      operationId: submitElections
      parameters:
        - $ref: '#/components/parameters/GroupId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ElectionsRequest'
            example:
              elections:
                - externalId: emp_1
                  election: enrolled
                  tier: employeeSpouse
                  dependents:
                    - relationship: spouse
                  effectiveDate: '2026-11-01'
                - externalId: emp_2
                  election: waived
                  waiverReason: other_employer_group
      responses:
        '200':
          description: Elections processed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ElectionsResult'
              example:
                groupId: grp_8c2f41d09a3e
                received: 2
                accepted: 2
                enrolled: 1
                waived: 1
                invited: 0
                invitesSuppressed: test-mode
                deductionsWebhook: true
                errors: []
        '400':
          description: The payload failed validation, or no election passed it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: invalid_request
                message: No election passed validation.
                details:
                  - field: elections[0].effectiveDate
                    message: effectiveDate is required for an enrolled election.
                    index: 0
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: The group has no enrollment yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: conflict
                message: Create the group's enrollment before submitting elections.
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    GroupId:
      name: groupId
      in: path
      required: true
      description: Group ID, e.g. `grp_8c2f41d09a3e`.
      schema:
        type: string
        pattern: ^grp_[0-9a-f]{12}$
      example: grp_8c2f41d09a3e
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Any non-empty string; deterministic keys from your own IDs work best.
        Repeating the same key with the same body on the same endpoint and mode
        within 24 hours returns the stored successful response (with
        `Idempotent-Replay: true`) instead of re-executing. Error responses are
        not stored.
      schema:
        type: string
      example: 9f3b2c61-4a8d-4e2f-b1c7-d5a90e8f1a23
  schemas:
    ElectionsRequest:
      type: object
      required:
        - elections
      properties:
        elections:
          type: array
          minItems: 1
          maxItems: 10000
          items:
            type: object
            required:
              - election
            description: >-
              Identify the employee by `memberId` or `externalId` (one is
              required).
            properties:
              memberId:
                type: string
              externalId:
                type: string
              election:
                type: string
                enum:
                  - enrolled
                  - waived
              tier:
                type: string
                enum:
                  - employeeOnly
                  - employeeSpouse
                  - employeeChildren
                  - family
                description: Must match the covered `dependents`.
              dependents:
                type: array
                description: The covered dependents.
                items:
                  type: object
                  required:
                    - relationship
                  properties:
                    relationship:
                      type: string
                      enum:
                        - spouse
                        - domestic_partner
                        - child
                        - other
                    dob:
                      type: string
                      format: date
                    name:
                      type: string
              effectiveDate:
                type: string
                format: date
                description: >-
                  Coverage effective date. Required when `election` is
                  `enrolled`.
              waiverReason:
                type: string
    ElectionsResult:
      type: object
      required:
        - groupId
        - received
        - accepted
        - enrolled
        - waived
        - invited
        - invitesSuppressed
        - deductionsWebhook
        - errors
      properties:
        groupId:
          type: string
        received:
          type: integer
        accepted:
          type: integer
        enrolled:
          type: integer
        waived:
          type: integer
        invited:
          type: integer
          description: Member login emails sent. None are sent in test mode.
        invitesSuppressed:
          type:
            - string
            - 'null'
          enum:
            - test-mode
            - null
        deductionsWebhook:
          type: boolean
          description: Whether a `deductions.changed` event was sent.
        errors:
          type: array
          items:
            type: object
            required:
              - field
              - message
            properties:
              field:
                type: string
              message:
                type: string
              index:
                type: integer
    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          enum:
            - invalid_request
            - unauthorized
            - live_mode_disabled
            - forbidden
            - not_found
            - conflict
            - rates_pending
            - quote_expired
            - market_unavailable
            - census_required
            - rate_limited
            - server_error
            - not_configured
            - email_not_allowed
            - verification_failed
          description: >-
            Stable machine-readable error code. `email_not_allowed` and
            `verification_failed` come only from the iframe's own endpoints,
            which partners do not call.
        message:
          type: string
          description: >-
            Human-readable explanation. Wording may change; branch on `error`,
            not `message`.
        details:
          type: array
          description: Present on `invalid_request`. One entry per failed field.
          items:
            type: object
            required:
              - field
              - message
            properties:
              field:
                type: string
                example: zip
              message:
                type: string
                example: zip must be a 5-digit ZIP code
              index:
                type: integer
                description: >-
                  For array payloads (census rows), the zero-based index of the
                  failing row.
                example: 7
  responses:
    Unauthorized:
      description: Missing, malformed, or revoked API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthorized
            message: >-
              Provide a valid partner API key as `Authorization: Bearer
              psk_...`.
    Forbidden:
      description: >-
        Key is live-mode but live mode is not enabled for this account, or the
        key may not access this resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: live_mode_disabled
            message: >-
              Live mode is not enabled for this account yet. Complete the
              go-live checklist to enable live keys.
    NotFound:
      description: >-
        No such resource in this mode. Test keys only see test resources; live
        keys only see live resources.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: not_found
            message: No group grp_8c2f41d09a3e found.
    RateLimited:
      description: Rate limit exceeded. Honor `Retry-After`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: rate_limited
            message: Too many requests. Please retry later.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
          example: 12
    ServerError:
      description: >-
        Something failed on our side. Safe to retry with the same
        `Idempotency-Key`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: server_error
            message: Internal error. The request was not applied.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Partner API key. `psk_test_<32 hex>` for test mode, `psk_live_<32 hex>`
        for live mode. Store them in your secrets manager on issue. Live keys
        are shown once; the scoped partner portal can show an active sandbox key
        again.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.