---
title: "Get program attachment"
method: GET
path: "/v1/products/attachments/programs/{programId}"
tags: ["Program attachment"]
---

# Get program attachment

`GET /v1/products/attachments/programs/{programId}`

## Request

- Base URL: `https://sandbox.pismolabs.io/savings-products`
- URL: `https://sandbox.pismolabs.io/savings-products/v1/products/attachments/programs/{programId}`
- Auth: HTTP bearer

Get a program's attached product.

## Path parameters

- `programId` integer, required

## Response `200`

Success

- ProgramAttachment
  - `product_type` 'deposit' | 'savings-account': Product type.
  - `product_id` string: Product identifier.
  - `interest_plan_id` string: Interest rate plan ID. This corresponds to the ID you created using the [Create interest plan version](ref:patch-v1-interest-plan)) endpoint.
  - `maturity_period` MaturityPeriod: Defines when the deposit matures. There are three usage modes: * **Relative period**: Sends `unit` + `value` (e.g. `MONTHS` + `6`). * **Explicit date**: Sends `calendar_maturity_date` (e.g. `2027-06-15`). * **Default**: Omits the field or sends `{}`. The product's configured default maturity term (`PRODUCT_DEFAULT_MATURITY_DATE_DAYS`, typically `10950` days ≈ 30 years) is applied. **NOTE**: `calendar_maturity_date` and `unit`/`value` are mutually exclusive, sending both in the same request returns a `400` validation error. In the **attach** endpoints, the response returns exactly what was sent in the request: * Send `unit` + `value` returns `unit` + `value` * Send `calendar_maturity_date` returns `calendar_maturity_date` * Send nothing (default fallback applied) returns `unit=DAYS` and `value` equal to the product's configured `PRODUCT_DEFAULT_MATURITY_DATE_DAYS` **NOTE**: this behavior applies only to attach. The `GET` attachment endpoints and `PATCH /v1/deposits/accounts/{accountId}/attachment` return the resolved term, with `unit`, `value`, and `calendar_maturity_date` populated together. A `PATCH` sent in explicit‑date form is returned normalized as `{unit: DAYS, value: <days>, calendar_maturity_date: <date>}`.
    - `unit` 'DAYS' | 'WEEKS' | 'MONTHS' | 'YEARS': Time unit for the relative maturity period. It's used together with `value` and cannot coincide with `calendar_maturity_date`. - `DAYS`: Uses `value` directly. Example: `value=90` → 90 days. - `WEEKS`: Multiplies `value` by 7. Example: `value=4` → 28 days. - `MONTHS`: Calculates calendar-month with end-of-month (EOM) clamping when the target day does not exist. The maturity date falls on the same day of the month as the start date. Example: `2026-09-22` + 3 months = `2026-12-22`; `2024-01-31` + 1 month = `2024-02-29` (leap year) or `2025-02-28` (non-leap year). - `YEARS`: Calculates calendar-year, for example: `2024-02-29` + 1 year = `2025-02-28`. Note that there is no Feb 29 in 2025. For `WEEKS`, `MONTHS`, and `YEARS`, the resulting calendar date is converted back to a day count to validate against the product's configured minimum or maximum term.
    - `value` integer: Number of time units until maturity. Must be greater than `0`. Mutually exclusive with `calendar_maturity_date`.
    - `calendar_maturity_date` string, date: Maturity date. Format is `YYYY-MM-DD`. The date must be a future date. This date cannot coincide with `unit`/`value`, sending both in the same request returns a `400` validation error.
  - `attachment_date` string, date-time: Timestamp that indicates when the attachment was created (when the attach API call was made). The datetime format follows the ISO 8601 standard `yyyy-mm-ddThh:mm:ss.sssZ`.
  - `effective_date` string, date: The effective date of the attachment in `YYYY-MM-DD` format This is the date when the attachment becomes valid. Maturity is calculated from this date. For attachments created in the past, the date defaults to the value of `attachment_date`.
  - `fee_model_id` string: Fee model identifier, if applicable.
  - `payout_account` PayoutAccount: The payout account defines where outbound payments are sent, and it is used in two operational contexts.<br> * **Capitalization flow**: When the capitalization mode is set to `PAYOUT`, the capitalized interest is directed to this account. If the mode is `REINVEST`, the payout account is not involved because the interest is added to the principal instead. * **Maturity instruction flow**: At maturity, this account receives principal or interest whenever the maturity instructions specify `PAY` for either `maturity_instructions.principal` or `maturity_instructions.interest`. This flow always relies on the payout account, regardless of how capitalization is configured. Both flows reference the same payout account settings. Choosing `REINVEST` for capitalization does not remove or disable the payout account, and it remains fully available for maturity‑related payments.
    - `label` string: Label to identify the account
    - `type` 'INTERNAL' | 'EXTERNAL': Payout account type, either `INTERNAL` or `EXTERNAL`
    - `internal_account_id` number: Internal account ID for the account that receives the payments. Required for type `INTERNAL` and not allowed for `EXTERNAL`.
    - `external_account` object: Contains user-defined key-value pairs that identify the external account receiving the payments. Note that external account information is client-provided. Required for type `EXTERNAL` and not allowed for `INTERNAL`.
  - `interest_capitalization_mode` 'PAYOUT' | 'REINVEST': Present only when this program attachment explicitly defines `interest_capitalization_mode`. If the field is missing, the Pismo platform applies `REINVEST` as the default behavior. All accounts linked to the program inherit this value unless an account‑level configuration provides its own setting.
  - `overrides` AttachmentOverridesSnapshot: Representation of the persisted overrides, present only when the request defined at least one override. Sub-fields are included only when set. The `renewal_term` always returns all three fields together (`unit`, `value` and `renewal_calendar_maturity_date`), mirroring the behavior of `maturity_period`.
    - `maturity_instructions` MaturityInstructionsOverrideRequest: Overrides the deposit’s behavior at maturity. If a field is omitted, the Pismo platform uses the value defined at the higher‑level configuration that governs this deposit.
      - `principal` 'ROLLOVER' | 'PAY': Specifies how the principal is handled once the deposit matures.
      - `interest` 'ROLLOVER' | 'PAY': Specifies how the interest is handled once the deposit matures.
      - `reason` string: Optional audit-trail reason.
    - `renewal_term` RenewalTermResponse: Renewal term applied on each rollover. Always returns all three fields together — `unit`, `value` and `renewal_calendar_maturity_date` — regardless of the form the client used to configure it, mirroring `maturity_period`. Legacy terms persisted before the calendar date was stored return only `unit`+`value`.
      - `unit` 'DAYS' | 'WEEKS' | 'MONTHS' | 'YEARS'
      - `value` integer
      - `renewal_calendar_maturity_date` string, date: Returned only when the request uses the calendar format. Format = `YYYY-MM-DD`.
    - `penalties` PenaltiesOverrideSnapshot: Persisted penalty overrides for each type. Types appear only when set. Each entry includes `waived`, the relevant type-specific fields, and an optional `valid_until` for scheduling the revert.
      - `reason` string
      - `grace_period` GracePeriodOverrideRequest: Grace period override. Type-specific fields are optional pointers, when omitted, the Pismo platform follows the normal fallback sequence, moving from the account level to the program and then to the product defaults.
        - `waived` boolean, required: `true` = fully exempt; `false` = penalty active (customize via the fields below).
        - `duration_days` integer
        - `penalty_interest_days` integer
        - `valid_until` string, date-time: Schedules the revert of this override via EventBridge. This value must be a future date and follows the ISO 8601 standard.
      - `early_withdrawal_after_opening` EarlyWithdrawalAfterOpeningOverrideRequest: Override for early withdrawal after account opening.
        - `waived` boolean, required
        - `applicable_within_days` integer
        - `penalty_interest_days` integer
        - `valid_until` string, date-time
      - `withdrawal_fee` WithdrawalFeeOverrideRequest: Withdrawal fee override.
        - `waived` boolean, required
        - `type` 'PERCENTAGE' | 'FIXED'
        - `value` number: Same format as the product's `withdrawal_fee.value`.
        - `valid_until` string, date-time
      - `tiered_interest_forfeiture` TieredInterestForfeitureOverrideRequest: Tiered interest forfeiture override. Tiers replace the product's tiers when provided.
        - `waived` boolean, required
        - `tiers` TieredInterestForfeitureTierRequest[]
          - `min_days_held` integer, required
          - `max_days_held` integer: Optional. Open-ended tier when omitted.
          - `forfeited_interest_days` integer, required
        - `valid_until` string, date-time
      - `subsequent_withdrawals` SubsequentWithdrawalsOverrideRequest: Subsequent withdrawals (Regulation D) override.
        - `waived` boolean, required
        - `applicable_within_days` integer
        - `penalty_interest_days` integer
        - `window_behavior` 'ROLLING' | 'FIXED'
        - `valid_until` string, date-time
  - `accrual_model` 'DEPOSIT_BASIS' | 'BALANCE_BASIS': Accrual model inherited from the attached product. `DEPOSIT_BASIS` or `BALANCE_BASIS`.
  - `balance_type` 'VALUE_DATED_BALANCE' | 'LEDGER_BALANCE': Balance type inherited from the attached product. Only meaningful when `accrual_model` is `BALANCE_BASIS`.

## Other responses

- `400`: Bad request
- `404`: Bad request
- `500`: Internal error

---

[API](https://skmtc.dev/pismo/apis/banking-interest-bearing-accounts.md) - [All operations](https://skmtc.dev/pismo/apis/banking-interest-bearing-accounts/llms.txt) - [OpenAPI document](https://skmtc.dev/pismo/apis/banking-interest-bearing-accounts/revisions/c68f61feb8a8?raw)
