Astrada bank-links API

Manage bank enrollment links. A bank link represents an invitation for a user to connect their bank account via Plaid.

OpenAPI Specification

astrada-bank-links-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Astrada bank-accounts bank-links API
  version: '2024-02-28'
  contact:
    email: developer@astrada.co
  description: 'Welcome to our API Reference. 👋

    '
servers:
- url: https://api.astrada.co
security: null
tags:
- name: bank-links
  description: Manage bank enrollment links. A bank link represents an invitation for a user to connect their bank account via Plaid.
paths:
  /bank-links:
    post:
      tags:
      - bank-links
      summary: Create bank link
      description: 'Creates a new bank link to initiate a bank enrollment. The response includes a `hostedLink` URL where the user can connect their bank account via Plaid.


        The hosted link expires after 4 hours. If the link expires before the user completes enrollment, retrieve the bank link via `GET /bank-links/{bankLinkId}` to get a refreshed URL.


        Creating a bank link with an ID that already exists for the account will return a `409 Conflict` error, unless the existing link has expired.

        '
      operationId: CreateBankLink
      security:
      - main-auth:
        - banking:write
      requestBody:
        description: Bank link creation request
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  description: A client-provided identifier for the bank link. Must be alphanumeric with hyphens and underscores only.
                  type: string
                  minLength: 1
                  maxLength: 256
                  pattern: ^[a-zA-Z0-9_-]+$
                subaccountId:
                  description: The subaccount identifier to associate with this bank link.
                  type: string
                  format: uuid
                filters:
                  type: object
                  description: 'Optional per-link narrowing of the account''s bank-linking policy. Values may

                    only NARROW what the policy allows — the current system default is

                    `accountTypes: [credit]` (credit-card accounts only). Requests widening beyond

                    the policy are rejected with `400`. Account-type enforcement is applied by the

                    provider at link-token creation and also filters the institution-select list.

                    '
                  properties:
                    accountTypes:
                      type: array
                      minItems: 1
                      description: Account types selectable during this hosted session.
                      items:
                        type: string
                        enum:
                        - checking
                        - savings
                        - credit
                    linkCustomizationName:
                      type: string
                      minLength: 1
                      maxLength: 100
                      description: 'Name of an allowlisted provider (Plaid) Link customization to apply to

                        this hosted session — e.g. `amex_only` to surface an Amex-first

                        institution list with a tailored headline for card-enrollment

                        connections. Only names on the account''s allowlist are accepted; others

                        are rejected with `400`. Institution steering is by account-type

                        filtering plus the customization''s Dashboard configuration — the

                        provider does not support hard institution pre-selection for hosted

                        sessions.

                        '
                bin6:
                  type: string
                  pattern: ^\d{6}$
                  description: 'First 6 digits captured client-side before an institution

                    pivot (e.g. an American Express BIN typed into the card form

                    before the SDK pivots to bank linking). Persisted with the

                    link and attached to the completion-time bank-derived card

                    mint when exactly one card is minted — it becomes that

                    card''s `first6digits`.

                    '
              required:
              - id
              - subaccountId
            examples:
              BankLinkRequestExample:
                value:
                  id: enrollment_abc123
                  subaccountId: 50cced63-ee4e-4ff7-a469-aaa989f220f2
              AmexCardEnrollmentExample:
                value:
                  id: enrollment_amex_7f2c
                  subaccountId: 50cced63-ee4e-4ff7-a469-aaa989f220f2
                  filters:
                    accountTypes:
                    - credit
                    linkCustomizationName: amex_only
                  bin6: '371449'
      responses:
        '201':
          description: Bank link created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/bank-link'
              examples:
                Example Create Bank Link Response:
                  value:
                    _links:
                      self:
                        href: /bank-links/enrollment_abc123
                    id: enrollment_abc123
                    accountId: 8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
                    subaccountId: 50cced63-ee4e-4ff7-a469-aaa989f220f2
                    state: pending
                    hostedLink: https://hosted.plaid.com/link/abc123
                    linkExpiresAt: '2025-10-03T14:25:27.000Z'
                    createdAt: '2025-10-03T10:25:27.069Z'
          links:
            GetBankLink:
              operationId: GetBankLink
              parameters:
                bankLinkId: $response.body#/id
              description: Retrieve the created bank link.
            CompleteBankLink:
              operationId: PatchBankLink
              parameters:
                bankLinkId: $response.body#/id
              description: Complete the bank link enrollment.
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '409':
          $ref: '#/components/responses/conflict'
        '500':
          $ref: '#/components/responses/server-error'
    get:
      tags:
      - bank-links
      summary: List bank links
      description: 'Returns a list of bank links under the account.


        By default, `GET /bank-links` returns bank links ordered by the latest `createdAt`.


        This endpoint supports cursor-based pagination.

        '
      operationId: ListBankLinks
      parameters:
      - $ref: '#/components/parameters/subaccount-id'
      - $ref: '#/components/parameters/bank-link-state'
      - $ref: '#/components/parameters/banking-limit'
      - $ref: '#/components/parameters/cursor'
      security:
      - main-auth:
        - banking:read
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                required:
                - items
                - pagination
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/bank-link'
                  pagination:
                    type: object
                    required:
                    - hasMore
                    properties:
                      cursor:
                        type: string
                        description: Cursor to use for the next page of results.
                      hasMore:
                        type: boolean
                        description: Whether there are more results available.
              examples:
                Example List Bank Links Response:
                  value:
                    items:
                    - _links:
                        self:
                          href: /bank-links/enrollment_792dcb7d
                        bankAccounts:
                        - href: /bank-accounts/3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c
                      id: enrollment_792dcb7d
                      accountId: 8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
                      subaccountId: 1fcb895e-9217-4a6f-9d10-5a7dcef86c11
                      state: completed
                      hostedLink: null
                      linkExpiresAt: null
                      completedAt: '2025-10-03T10:55:42.000Z'
                      bankAccounts:
                      - id: 3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c
                        name: Checking
                      createdAt: '2025-10-03T10:25:27.069Z'
                    - _links:
                        self:
                          href: /bank-links/enrollment_a1b2c3d4
                      id: enrollment_a1b2c3d4
                      accountId: 8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
                      subaccountId: 1fcb895e-9217-4a6f-9d10-5a7dcef86c11
                      state: pending
                      hostedLink: https://hosted.plaid.com/link/abc123
                      linkExpiresAt: '2025-10-04T14:25:27.000Z'
                      createdAt: '2025-10-04T10:25:27.069Z'
                    pagination:
                      cursor: ZXhhbXBsZQ==
                      hasMore: false
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '500':
          $ref: '#/components/responses/server-error'
  /bank-links/{bankLinkId}:
    parameters:
    - $ref: '#/components/parameters/bank-link-id'
    delete:
      tags:
      - bank-links
      summary: Delete bank link
      description: 'Deletes a bank link and all associated resources, including the bank subscription, bank accounts, and bank transactions.


        **Note:** This action is irreversible and will revoke access to the connected financial institution.

        '
      operationId: DeleteBankLink
      security:
      - main-auth:
        - banking:admin
      responses:
        '204':
          description: Bank link deleted
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '409':
          $ref: '#/components/responses/conflict'
        '500':
          $ref: '#/components/responses/server-error'
    get:
      tags:
      - bank-links
      summary: Retrieve bank link
      description: 'Returns detailed information about a specific bank link by its identifier.


        If the bank link is in `pending` state and the hosted link URL has expired, this endpoint will automatically refresh the URL and return the updated link.

        '
      operationId: GetBankLink
      security:
      - main-auth:
        - banking:read
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/bank-link'
              examples:
                Example Get Bank Link Response:
                  $ref: '#/components/examples/bank-link'
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '500':
          $ref: '#/components/responses/server-error'
    patch:
      tags:
      - bank-links
      summary: Complete bank link
      description: 'Completes a bank link enrollment, transitioning it from `pending` to `completed` state. The request body must contain `state: "completed"`.


        When a bank link is completed, the system exchanges the enrollment credentials with the provider, creates a bank subscription (connection), and discovers the associated bank accounts.


        This endpoint is idempotent — completing an already completed bank link returns the existing subscription and accounts.

        '
      operationId: PatchBankLink
      security:
      - main-auth:
        - banking:write
      requestBody:
        description: Bank link completion request
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                state:
                  description: The target state for the bank link. Only `completed` is accepted.
                  type: string
                  enum:
                  - completed
              required:
              - state
            examples:
              BankLinkRequestExample:
                value:
                  state: completed
      responses:
        '200':
          description: Bank link completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/bank-link'
              examples:
                Example Complete Bank Link Response:
                  $ref: '#/components/examples/bank-link'
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '409':
          $ref: '#/components/responses/conflict'
        '500':
          $ref: '#/components/responses/server-error'
  /bank-links/{bankLinkId}/sync:
    parameters:
    - $ref: '#/components/parameters/bank-link-id'
    post:
      tags:
      - bank-links
      summary: Sync bank link
      description: 'Triggers a manual sync of transactions for the bank link''s associated subscription. This fetches the latest transactions from the financial institution.


        Transaction syncs also occur automatically via provider webhooks and scheduled jobs. Use this endpoint to force an immediate sync when needed.

        '
      operationId: SyncBankLink
      security:
      - main-auth:
        - banking:admin
      requestBody:
        description: Optional sync configuration
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                webhooks:
                  description: The types of webhook events to emit after syncing.
                  type: array
                  items:
                    type: string
                    enum:
                    - banktransaction.created
                    - transaction.match.created
                force:
                  description: Set to `true` to force a full sync even if no new transactions are detected.
                  type: boolean
                  default: false
            examples:
              SyncWithWebhooksExample:
                value:
                  webhooks:
                  - banktransaction.created
                  force: false
      responses:
        '200':
          description: Sync triggered
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Human-readable confirmation message.
              examples:
                Example Sync Response:
                  value:
                    message: Transactions synced successfully
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '409':
          $ref: '#/components/responses/conflict'
        '500':
          $ref: '#/components/responses/server-error'
  /bank-links/{bankLinkId}/webhook:
    parameters:
    - $ref: '#/components/parameters/bank-link-id'
    patch:
      tags:
      - bank-links
      summary: Update bank link webhook
      description: 'Updates the webhook URL for a bank link. Webhook events related to this bank link and its associated resources will be delivered to the specified URL.


        After updating, the webhook status will be set to `pending` until the provider acknowledges the new URL, at which point it transitions to `confirmed`.

        '
      operationId: UpdateBankLinkWebhook
      security:
      - main-auth:
        - banking:admin
      requestBody:
        description: Webhook URL update request
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                webhookUrl:
                  description: The HTTPS URL where webhook events will be delivered.
                  type: string
                  format: uri
              required:
              - webhookUrl
            examples:
              UpdateWebhookExample:
                value:
                  webhookUrl: https://example.com/webhooks/banking
      responses:
        '200':
          description: Webhook URL updated
          content:
            application/json:
              schema:
                type: object
                required:
                - status
                - message
                - webhookUrl
                properties:
                  status:
                    type: string
                    description: The webhook update status. Always `pending` immediately after updating.
                    enum:
                    - pending
                  message:
                    type: string
                    description: Human-readable confirmation message.
                  webhookUrl:
                    type: string
                    description: The webhook URL that was requested for update.
              examples:
                Example Update Webhook Response:
                  value:
                    status: pending
                    message: Webhook update requested. The update will be confirmed when a WEBHOOK_UPDATE_ACKNOWLEDGED webhook is received from Plaid.
                    webhookUrl: https://example.com/webhooks/banking
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '409':
          $ref: '#/components/responses/conflict'
        '500':
          $ref: '#/components/responses/server-error'
components:
  parameters:
    subaccount-id:
      in: query
      name: subaccountId
      required: false
      schema:
        type: string
        format: uuid
      example: 2fd4d402-b759-479c-87a6-58d85e345356
    bank-link-state:
      in: query
      name: state
      description: Filter bank links by state
      required: false
      schema:
        type: string
        enum:
        - pending
        - completed
        - expired
      example: completed
    banking-limit:
      in: query
      name: limit
      description: Maximum number of items to return
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 1000
        default: 250
      example: 250
    bank-link-id:
      in: path
      name: bankLinkId
      description: The client-provided identifier of the bank link.
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 256
        pattern: ^[a-zA-Z0-9_-]+$
      example: enrollment_792dcb7d
    cursor:
      in: query
      name: cursor
      required: false
      description: The cursor to use for pagination. Identifies your place on the list
      schema:
        type: string
        format: byte
      example: ZXhhbXBsZQ==
  responses:
    conflict:
      description: Request conflict with the current state of the target resource
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/conflict'
          examples:
            Minimum shape (detail only):
              value:
                detail: Card verification with id=9fab1bea-bc1e-4757-bd47-479422e5983b was abandoned by the user during the authentication process. Please start a new verification.
            Resource conflict with currentValue:
              value:
                title: Conflict
                detail: The target resource already exists.
                currentValue: 396aebd2-002f-4ccf-9b4d-f961c693e6e2
    not-found:
      description: The requested resource was not found on the server
      content:
        application/problem+json:
          schema:
            type: object
            properties:
              type:
                type: string
              instance:
                type: string
              detail:
                type: string
              title:
                type: string
                enum:
                - Not Found
            required:
            - detail
            - title
          example:
            title: Not Found
            detail: The requested resource was not found on the server.
    unauthorized:
      description: Authentication credentials were either missing or incorrect
      content:
        application/problem+json:
          schema:
            type: object
            properties:
              detail:
                type: string
              title:
                type: string
                enum:
                - Unauthorized
            required:
            - detail
            - title
          example:
            title: Unauthorized
            detail: Authentication credentials were either missing or incorrect.
    forbidden:
      description: Authentication credentials used do not have have permissions to perform the request
      content:
        application/problem+json:
          schema:
            type: object
            properties:
              detail:
                type: string
              title:
                type: string
                enum:
                - Forbidden
            required:
            - detail
            - title
          example:
            title: Forbidden
            detail: You do not have permission to access the requested resource.
    server-error:
      description: The server encountered an unexpected condition that prevented it from fulfilling the request
      content:
        application/problem+json:
          schema:
            type: object
            properties:
              detail:
                type: string
              title:
                type: string
                enum:
                - Internal Server Error
            required:
            - detail
            - title
          example:
            title: Internal Server Error
            detail: The server encountered an unexpected condition that prevented it from fulfilling the request.
    bad-request:
      description: The server cannot or will not process the request due to something that is perceived to be a client error
      content:
        application/problem+json:
          schema:
            type: object
            properties:
              detail:
                type: string
              title:
                type: string
                enum:
                - Bad Request
              errors:
                type: array
                items:
                  type: object
                  properties:
                    title:
                      type: string
                    detail:
                      type: string
                  required:
                  - title
                  - detail
            required:
            - detail
            - title
          examples:
            Example Generic Bad Request Payload Response:
              value:
                title: Bad Request
                detail: Request object failed validation.
            Example Generic Bad Request Parameters Response:
              value:
                title: Bad Request
                detail: Request parameters are invalid.
  examples:
    bank-link:
      description: Example of a completed Bank Link resource
      value:
        _links:
          self:
            href: /bank-links/enrollment_792dcb7d
          bankAccounts:
          - href: /bank-accounts/3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c
        id: enrollment_792dcb7d
        accountId: 8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
        subaccountId: 1fcb895e-9217-4a6f-9d10-5a7dcef86c11
        state: completed
        hostedLink: null
        linkExpiresAt: null
        completedAt: '2025-10-03T10:55:42.000Z'
        bankAccounts:
        - id: 3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c
          name: Checking
        createdAt: '2025-10-03T10:25:27.069Z'
  schemas:
    conflict:
      type: object
      properties:
        detail:
          type: string
        title:
          type: string
          enum:
          - Conflict
        currentValue:
          type: string
          description: Current value for the property causing the conflict
        requestedValue:
          type: string
          description: Requested value for the property causing the conflict
      required:
      - detail
    link:
      type: object
      properties:
        href:
          type: string
        templated:
          type: boolean
        type:
          type: string
        deprecation:
          type: string
        name:
          type: string
        profile:
          type: string
        title:
          type: string
        hreflang:
          type: string
      required:
      - href
    bank-link:
      type: object
      required:
      - _links
      - id
      - accountId
      - subaccountId
      - state
      - hostedLink
      - linkExpiresAt
      - createdAt
      properties:
        _links:
          type: object
          description: HAL-style links to related resources.
          required:
          - self
          properties:
            self:
              $ref: '#/components/schemas/link'
            bankAccounts:
              type: array
              description: Links to the bank accounts created from this link. Only present when state is `completed` and accounts exist.
              items:
                $ref: '#/components/schemas/link'
        id:
          type: string
          description: The client-provided identifier of the bank link. Must be alphanumeric with hyphens and underscores only.
          minLength: 1
          maxLength: 256
          pattern: ^[a-zA-Z0-9_-]+$
        accountId:
          type: string
          format: uuid
          description: The unique identifier of the account that owns this bank link.
        subaccountId:
          type: string
          format: uuid
          description: The unique identifier of the subaccount associated with this bank link.
        state:
          type: string
          description: 'Current state of the bank link.

            - `pending`: The link has been created and is awaiting user enrollment.

            - `completed`: The user has successfully connected their bank account.

            - `expired`: The link has expired without being completed.

            '
          enum:
          - pending
          - completed
          - expired
        hostedLink:
          type: string
          nullable: true
          description: The hosted URL where the user can complete the bank enrollment. This link expires after 4 hours and is automatically refreshed when retrieved via GET.
        linkExpiresAt:
          description: Date and time when the hosted link expires, in UTC, following ISO 8601 format.
          type: string
          format: date-time
          nullable: true
        completedAt:
          description: Date and time when the bank link enrollment was completed, in UTC, following ISO 8601 format. Only present when state is `completed`.
          type: string
          format: date-time
        filters:
          type: object
          description: 'The account filtering actually applied to this link, after resolution against the

            account''s bank-linking policy. Echoes what the hosted session will offer; absent on

            links created before filtering existed.

            '
          properties:
            accountTypes:
              type: array
              description: Account types selectable in the hosted session.
              items:
                type: string
                enum:
                - checking
                - savings
                - credit
            institutionId:
              type: string
              description: 'Provider institution id (Plaid `ins_*`) recorded and validated for this

                session. Informational — steering is via account-type filters and Dashboard

                Link customization; the provider does not currently support hard

                pre-selection for hosted sessions.

                '
              pattern: ^ins_[A-Za-z0-9]+$
        bankAccounts:
          type: array
          description: Summary of bank accounts created from this link. Only present when state is `completed` and accounts exist.
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
                description: The bank account identifier.
              name:
                type: string
                description: The display name of the bank account.
              mask:
                type: string
                nullable: true
                description: 'Last 4 digits of the account number. For `credit` accounts this is the card

                  number''s last 4 — the per-card identity for bank-connected (e.g. American

                  Express) enrollments. Not guaranteed per-card when the institution combines

                  multiple cards into one account.

                  '
              type:
                type: string
                nullable: true
                description: Normalized account type (e.g. `checking`, `savings`, `credit`).
              cardIds:
                type: array
                description: 'Identifiers of already-enrolled cards linked to this account — matched

                  immediately at completion when an enrolled card''s last 4 equals a credit

                  account''s mask, and over time by transaction-based discovery. A link is an

                  association to an EXISTING card, not a new enrollment.

                  '
                items:
                  type: string
                  format: uuid
              cards:
                type: array
                description: 'Cards created from this account at completion (`bank-feed` enrollments),

                  each paired with its subscription. Present only on credit accounts that

                  created a card; a created card also appears in `cardIds`.

                  '
                items:
                  type: object
                  required:
                  - id
                  - subscriptionId
                  - last4digits
                  - network
                  - enrollmentType
                  properties:
                    id:
                      type: string
                      format: uuid
                    subscriptionId:
                      type: string
                      format: uuid
                    last4digits:
                      type: string
                      pattern: ^\d{4}$
                    network:
                      type: string
                      nullable: true
                    enrollmentType:
                      type: string
                      enum:
                      - bank-feed
        createdAt:
          description: Date and time when this resource was created, in UTC, following ISO 8601 format.
          type: string
          format: date-time
  securitySchemes:
    main-auth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://api.astrada.co/auth/realms/{accountId}/protocol/openid-connect/toke

# --- truncated at 32 KB (34 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/astrada/refs/heads/main/openapi/astrada-bank-links-api-openapi.yml