# Commitment Plan Templates (Beta)

Agent-friendly commitment plan template endpoints

## List commitment plan templates

> Returns commitment plan templates scoped to one segment for the given provider. \`segment\_id\` defaults to the provider-resources segment — same fallback as POST/PUT — so the typical caller sees exactly the templates tied to their default segment without cross-segment duplicates.

```json
{"openapi":"3.0.2","info":{"title":"Archera.ai Beta API","version":"v1.0.0"},"tags":[{"name":"Commitment Plan Templates (Beta)","description":"Agent-friendly commitment plan template endpoints"}],"paths":{"/beta/v1/org/{org_id}/commitment-plan-templates":{"get":{"parameters":[{"in":"query","name":"provider","description":"Cloud provider (aws, azure, gcp)","schema":{"type":"string","enum":["aws","azure","gcp","kubernetes","unknown"]},"required":true},{"in":"query","name":"segment_id","description":"Optional segment ID to scope results. Defaults to the provider resources segment if not specified.","schema":{"type":"string","format":"uuid","default":null,"nullable":true},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CommitmentPlanTemplate"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"$ref":"#/components/responses/UNPROCESSABLE_CONTENT"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"default":{"$ref":"#/components/responses/DEFAULT_ERROR"}},"tags":["Commitment Plan Templates (Beta)"],"summary":"List commitment plan templates","description":"Returns commitment plan templates scoped to one segment for the given provider. `segment_id` defaults to the provider-resources segment — same fallback as POST/PUT — so the typical caller sees exactly the templates tied to their default segment without cross-segment duplicates."}}},"components":{"schemas":{"CommitmentPlanTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique template identifier"},"name":{"type":"string","description":"Human-readable template name"},"segment_id":{"type":"string","format":"uuid","description":"Segment this template generates plans for"},"created_at":{"type":"string","format":"date-time","description":"When the template was created"},"is_system_generated":{"type":"boolean","description":"True if this template was created automatically by the system — the three built-ins that back Recommended / Balanced / High Savings. Describes origin, not role — system-generated templates are immutable."},"configuration":{"description":"The inputs that plans generated from this template will use","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"description":"Scheduled auto-purchase settings, or null if the template is not on a schedule.","anyOf":[{"$ref":"#/components/schemas/AutoPurchase"},{"type":"object","nullable":true}]}},"required":["auto_purchase","configuration","created_at","id","is_system_generated","name","segment_id"],"additionalProperties":false},"CommitmentPlanConfiguration":{"type":"object","properties":{"max_upfront_cost":{"type":"number","default":0,"description":"Cap on the one-time upfront dollars the generated plan is allowed to include. Defaults to 0 — the recommender excludes any line item with an upfront cost. Pass null to lift the cap entirely. Otherwise, line items with upfront costs are excluded if adding them would exceed the cap.","nullable":true},"lookback_days":{"type":"integer","default":null,"description":"How many days of historical usage to feed into plan generation. Defaults to 7 when omitted — matches the recommender's default and gives a representative recent-week baseline. Increase for workloads with weekly/seasonal variance. NULL on renewal plans: renewals derive their usage window from the source commitments' end dates, so this field has no effect. Sending a non-null value to a renewal plan PUT is rejected so round-tripping is honest.","nullable":true},"contract_specs":{"description":"List of contract specs to consider when generating the plan. Each spec is a triple of (commitment_type, contract_term, payment_option). The plan generator will pick the best mix of offerings matching these specs.","type":"array","items":{"$ref":"#/components/schemas/ConfigurationContractSpec"}},"resource_ids":{"type":"array","default":null,"description":"Optional list of resource composite ids (`<resource_id>|<catalog_sku_org_id>|<catalog_sku_id>`, the same form returned as `id` on resource-SKU responses) to scope the generated plan to specific resources. When non-empty, the plan's coverage is restricted to these resources and the plan is created as an infrastructure plan — line items only attempt to cover the listed resources rather than the whole segment. Mutually exclusive with `renewal_commitment_ids` (a plan can be scoped by resources OR scoped by renewing commitments, not both). Usually omitted; supply only when the user has explicitly named the resources to cover. Templates do not accept this field — supplying it on a template create/update is rejected.","items":{},"nullable":true},"renewal_commitment_ids":{"type":"array","default":null,"description":"Optional list of expiring commitment ids the plan is renewing. When non-empty, the plan is a renewal: coverage is built from the source commitments' historical usage, and each generated line item carries a `renewal_commitment_id` linking back to the source it proposes to replace. Mutually exclusive with `resource_ids`. On a renewal plan PUT this re-targets which commitments are being renewed (recalc); on a non-renewal plan PUT, sending this is rejected (use the dedicated POST /commitment-plans/renewals to create a renewal). Read-back unchanged from a GET so the configuration round-trips through PUT.","items":{"type":"string","format":"uuid"},"nullable":true}},"required":["contract_specs"],"additionalProperties":false},"ConfigurationContractSpec":{"type":"object","properties":{"commitment_type":{"type":"string","description":"Commitment type identifier — e.g. 'aws/savingsplan/Compute', 'aws/AmazonEC2', 'aws/AmazonRDS'. Values are provider-prefixed; fetch the exact list from GET /commitment-types and pass through verbatim. Rejected with 422 if the identifier is unknown across all providers; the validator does not enforce that the type belongs to the request's `provider` (a mismatched-but-real type will pass schema validation and produce a plan with no line items)."},"contract_term":{"description":"Commitment term (e.g. 'thirty_day_gris', 'one_year_gris', 'one_year', 'three_year'). Validated against the catalog entry for the supplied commitment_type — invalid (type, term) pairs are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["one_year_gris","thirty_day_gris","two_month_gris","three_month_gris","four_month_gris","five_month_gris","six_month_gris","seven_month_gris","eight_month_gris","nine_month_gris","ten_month_gris","eleven_month_gris","twelve_month_gris","thirteen_month_gris","fourteen_month_gris","fifteen_month_gris","sixteen_month_gris","seventeen_month_gris","eighteen_month_gris","nineteen_month_gris","twenty_month_gris","twenty_one_month_gris","twenty_two_month_gris","twenty_three_month_gris","twenty_four_month_gris","twenty_five_month_gris","twenty_six_month_gris","twenty_seven_month_gris","twenty_eight_month_gris","twenty_nine_month_gris","thirty_month_gris","thirty_one_month_gris","thirty_two_month_gris","thirty_three_month_gris","thirty_four_month_gris","thirty_five_month_gris","one_year","two_year","three_year","five_year","zero_day","thirty_day","two_month","three_month","four_month","five_month","six_month","seven_month","eight_month","nine_month","ten_month","eleven_month","thirteen_month","fourteen_month","fifteen_month","sixteen_month","seventeen_month","eighteen_month","nineteen_month","twenty_month","twenty_one_month","twenty_two_month","twenty_three_month","twenty_five_month","twenty_six_month","twenty_seven_month","twenty_eight_month","twenty_nine_month","thirty_month","thirty_one_month","thirty_two_month","thirty_three_month","thirty_four_month","thirty_five_month"]},"payment_option":{"description":"Payment option (e.g. 'no_upfront', 'partial_upfront', 'all_upfront'). Validated against the catalog entry for the supplied (commitment_type, contract_term) pair — invalid triples are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["no_upfront","partial_upfront","all_upfront"]}},"required":["commitment_type","contract_term","payment_option"],"additionalProperties":false},"AutoPurchase":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the schedule is currently active"},"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","description":"Dollar floor on projected monthly savings — plans that don't clear this are skipped even when the schedule fires."},"start_date":{"type":"string","format":"date","description":"Earliest date the automation may fire (inclusive). Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","description":"Latest date the automation may fire (inclusive). Null = no upper bound.","nullable":true},"next_execution_date":{"type":"string","format":"date","description":"When the next automated run is scheduled (computed)"},"last_executed_at":{"type":"string","format":"date-time","description":"When the last automated run fired, or null if it has not yet","nullable":true}},"required":["enabled","end_date","min_monthly_savings","schedule","start_date"],"additionalProperties":false},"ApiErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"detail":{"nullable":true},"code":{"type":"string","nullable":true},"url":{"type":"string","nullable":true},"timestamp":{"type":"string"},"type":{"type":"string"}},"required":["message","timestamp","type"]},"Error":{"type":"object","properties":{"code":{"type":"integer","description":"Error code"},"status":{"type":"string","description":"Error name"},"message":{"type":"string","description":"Error message"},"errors":{"type":"object","description":"Errors","additionalProperties":{}}},"additionalProperties":false}},"responses":{"UNPROCESSABLE_CONTENT":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"DEFAULT_ERROR":{"description":"Default error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}
```

## Create a commitment plan template

> Creates a reusable commitment plan template. If \`auto\_purchase\` is provided, the system will regenerate and optionally purchase plans from this template on the given schedule.

```json
{"openapi":"3.0.2","info":{"title":"Archera.ai Beta API","version":"v1.0.0"},"tags":[{"name":"Commitment Plan Templates (Beta)","description":"Agent-friendly commitment plan template endpoints"}],"paths":{"/beta/v1/org/{org_id}/commitment-plan-templates":{"post":{"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitmentPlanTemplate"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"$ref":"#/components/responses/UNPROCESSABLE_CONTENT"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"default":{"$ref":"#/components/responses/DEFAULT_ERROR"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommitmentPlanTemplateArgs"}}}},"tags":["Commitment Plan Templates (Beta)"],"summary":"Create a commitment plan template","description":"Creates a reusable commitment plan template. If `auto_purchase` is provided, the system will regenerate and optionally purchase plans from this template on the given schedule."}}},"components":{"schemas":{"CommitmentPlanTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique template identifier"},"name":{"type":"string","description":"Human-readable template name"},"segment_id":{"type":"string","format":"uuid","description":"Segment this template generates plans for"},"created_at":{"type":"string","format":"date-time","description":"When the template was created"},"is_system_generated":{"type":"boolean","description":"True if this template was created automatically by the system — the three built-ins that back Recommended / Balanced / High Savings. Describes origin, not role — system-generated templates are immutable."},"configuration":{"description":"The inputs that plans generated from this template will use","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"description":"Scheduled auto-purchase settings, or null if the template is not on a schedule.","anyOf":[{"$ref":"#/components/schemas/AutoPurchase"},{"type":"object","nullable":true}]}},"required":["auto_purchase","configuration","created_at","id","is_system_generated","name","segment_id"],"additionalProperties":false},"CommitmentPlanConfiguration":{"type":"object","properties":{"max_upfront_cost":{"type":"number","default":0,"description":"Cap on the one-time upfront dollars the generated plan is allowed to include. Defaults to 0 — the recommender excludes any line item with an upfront cost. Pass null to lift the cap entirely. Otherwise, line items with upfront costs are excluded if adding them would exceed the cap.","nullable":true},"lookback_days":{"type":"integer","default":null,"description":"How many days of historical usage to feed into plan generation. Defaults to 7 when omitted — matches the recommender's default and gives a representative recent-week baseline. Increase for workloads with weekly/seasonal variance. NULL on renewal plans: renewals derive their usage window from the source commitments' end dates, so this field has no effect. Sending a non-null value to a renewal plan PUT is rejected so round-tripping is honest.","nullable":true},"contract_specs":{"description":"List of contract specs to consider when generating the plan. Each spec is a triple of (commitment_type, contract_term, payment_option). The plan generator will pick the best mix of offerings matching these specs.","type":"array","items":{"$ref":"#/components/schemas/ConfigurationContractSpec"}},"resource_ids":{"type":"array","default":null,"description":"Optional list of resource composite ids (`<resource_id>|<catalog_sku_org_id>|<catalog_sku_id>`, the same form returned as `id` on resource-SKU responses) to scope the generated plan to specific resources. When non-empty, the plan's coverage is restricted to these resources and the plan is created as an infrastructure plan — line items only attempt to cover the listed resources rather than the whole segment. Mutually exclusive with `renewal_commitment_ids` (a plan can be scoped by resources OR scoped by renewing commitments, not both). Usually omitted; supply only when the user has explicitly named the resources to cover. Templates do not accept this field — supplying it on a template create/update is rejected.","items":{},"nullable":true},"renewal_commitment_ids":{"type":"array","default":null,"description":"Optional list of expiring commitment ids the plan is renewing. When non-empty, the plan is a renewal: coverage is built from the source commitments' historical usage, and each generated line item carries a `renewal_commitment_id` linking back to the source it proposes to replace. Mutually exclusive with `resource_ids`. On a renewal plan PUT this re-targets which commitments are being renewed (recalc); on a non-renewal plan PUT, sending this is rejected (use the dedicated POST /commitment-plans/renewals to create a renewal). Read-back unchanged from a GET so the configuration round-trips through PUT.","items":{"type":"string","format":"uuid"},"nullable":true}},"required":["contract_specs"],"additionalProperties":false},"ConfigurationContractSpec":{"type":"object","properties":{"commitment_type":{"type":"string","description":"Commitment type identifier — e.g. 'aws/savingsplan/Compute', 'aws/AmazonEC2', 'aws/AmazonRDS'. Values are provider-prefixed; fetch the exact list from GET /commitment-types and pass through verbatim. Rejected with 422 if the identifier is unknown across all providers; the validator does not enforce that the type belongs to the request's `provider` (a mismatched-but-real type will pass schema validation and produce a plan with no line items)."},"contract_term":{"description":"Commitment term (e.g. 'thirty_day_gris', 'one_year_gris', 'one_year', 'three_year'). Validated against the catalog entry for the supplied commitment_type — invalid (type, term) pairs are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["one_year_gris","thirty_day_gris","two_month_gris","three_month_gris","four_month_gris","five_month_gris","six_month_gris","seven_month_gris","eight_month_gris","nine_month_gris","ten_month_gris","eleven_month_gris","twelve_month_gris","thirteen_month_gris","fourteen_month_gris","fifteen_month_gris","sixteen_month_gris","seventeen_month_gris","eighteen_month_gris","nineteen_month_gris","twenty_month_gris","twenty_one_month_gris","twenty_two_month_gris","twenty_three_month_gris","twenty_four_month_gris","twenty_five_month_gris","twenty_six_month_gris","twenty_seven_month_gris","twenty_eight_month_gris","twenty_nine_month_gris","thirty_month_gris","thirty_one_month_gris","thirty_two_month_gris","thirty_three_month_gris","thirty_four_month_gris","thirty_five_month_gris","one_year","two_year","three_year","five_year","zero_day","thirty_day","two_month","three_month","four_month","five_month","six_month","seven_month","eight_month","nine_month","ten_month","eleven_month","thirteen_month","fourteen_month","fifteen_month","sixteen_month","seventeen_month","eighteen_month","nineteen_month","twenty_month","twenty_one_month","twenty_two_month","twenty_three_month","twenty_five_month","twenty_six_month","twenty_seven_month","twenty_eight_month","twenty_nine_month","thirty_month","thirty_one_month","thirty_two_month","thirty_three_month","thirty_four_month","thirty_five_month"]},"payment_option":{"description":"Payment option (e.g. 'no_upfront', 'partial_upfront', 'all_upfront'). Validated against the catalog entry for the supplied (commitment_type, contract_term) pair — invalid triples are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["no_upfront","partial_upfront","all_upfront"]}},"required":["commitment_type","contract_term","payment_option"],"additionalProperties":false},"AutoPurchase":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the schedule is currently active"},"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","description":"Dollar floor on projected monthly savings — plans that don't clear this are skipped even when the schedule fires."},"start_date":{"type":"string","format":"date","description":"Earliest date the automation may fire (inclusive). Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","description":"Latest date the automation may fire (inclusive). Null = no upper bound.","nullable":true},"next_execution_date":{"type":"string","format":"date","description":"When the next automated run is scheduled (computed)"},"last_executed_at":{"type":"string","format":"date-time","description":"When the last automated run fired, or null if it has not yet","nullable":true}},"required":["enabled","end_date","min_monthly_savings","schedule","start_date"],"additionalProperties":false},"ApiErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"detail":{"nullable":true},"code":{"type":"string","nullable":true},"url":{"type":"string","nullable":true},"timestamp":{"type":"string"},"type":{"type":"string"}},"required":["message","timestamp","type"]},"Error":{"type":"object","properties":{"code":{"type":"integer","description":"Error code"},"status":{"type":"string","description":"Error name"},"message":{"type":"string","description":"Error message"},"errors":{"type":"object","description":"Errors","additionalProperties":{}}},"additionalProperties":false},"CreateCommitmentPlanTemplateArgs":{"type":"object","properties":{"provider":{"description":"Cloud provider (aws, azure, gcp)","type":"string","enum":["aws","azure","gcp","kubernetes","unknown"]},"segment_id":{"type":"string","format":"uuid","default":null,"description":"Optional segment ID to scope results. Defaults to the provider resources segment if not specified.","nullable":true},"name":{"type":"string","description":"Template name"},"configuration":{"description":"Plan configuration this template applies","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"default":null,"description":"Optional auto-purchase schedule to attach","anyOf":[{"$ref":"#/components/schemas/CreateAutoPurchase"},{"type":"object","nullable":true}]}},"required":["configuration","name","provider"],"additionalProperties":false},"CreateAutoPurchase":{"type":"object","properties":{"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","default":0,"description":"Dollar floor on projected monthly savings"},"enabled":{"type":"boolean","default":true,"description":"Whether the schedule is active"},"start_date":{"type":"string","format":"date","default":null,"description":"Earliest date automation may fire. Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","default":null,"description":"Latest date automation may fire. Null = no upper bound.","nullable":true}},"required":["schedule"],"additionalProperties":false}},"responses":{"UNPROCESSABLE_CONTENT":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"DEFAULT_ERROR":{"description":"Default error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}
```

## Get a commitment plan template

> Returns a single template by ID.

```json
{"openapi":"3.0.2","info":{"title":"Archera.ai Beta API","version":"v1.0.0"},"tags":[{"name":"Commitment Plan Templates (Beta)","description":"Agent-friendly commitment plan template endpoints"}],"paths":{"/beta/v1/org/{org_id}/commitment-plan-templates/{template_id}":{"get":{"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitmentPlanTemplate"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not Found"},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"default":{"$ref":"#/components/responses/DEFAULT_ERROR"}},"tags":["Commitment Plan Templates (Beta)"],"summary":"Get a commitment plan template","description":"Returns a single template by ID."}}},"components":{"schemas":{"CommitmentPlanTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique template identifier"},"name":{"type":"string","description":"Human-readable template name"},"segment_id":{"type":"string","format":"uuid","description":"Segment this template generates plans for"},"created_at":{"type":"string","format":"date-time","description":"When the template was created"},"is_system_generated":{"type":"boolean","description":"True if this template was created automatically by the system — the three built-ins that back Recommended / Balanced / High Savings. Describes origin, not role — system-generated templates are immutable."},"configuration":{"description":"The inputs that plans generated from this template will use","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"description":"Scheduled auto-purchase settings, or null if the template is not on a schedule.","anyOf":[{"$ref":"#/components/schemas/AutoPurchase"},{"type":"object","nullable":true}]}},"required":["auto_purchase","configuration","created_at","id","is_system_generated","name","segment_id"],"additionalProperties":false},"CommitmentPlanConfiguration":{"type":"object","properties":{"max_upfront_cost":{"type":"number","default":0,"description":"Cap on the one-time upfront dollars the generated plan is allowed to include. Defaults to 0 — the recommender excludes any line item with an upfront cost. Pass null to lift the cap entirely. Otherwise, line items with upfront costs are excluded if adding them would exceed the cap.","nullable":true},"lookback_days":{"type":"integer","default":null,"description":"How many days of historical usage to feed into plan generation. Defaults to 7 when omitted — matches the recommender's default and gives a representative recent-week baseline. Increase for workloads with weekly/seasonal variance. NULL on renewal plans: renewals derive their usage window from the source commitments' end dates, so this field has no effect. Sending a non-null value to a renewal plan PUT is rejected so round-tripping is honest.","nullable":true},"contract_specs":{"description":"List of contract specs to consider when generating the plan. Each spec is a triple of (commitment_type, contract_term, payment_option). The plan generator will pick the best mix of offerings matching these specs.","type":"array","items":{"$ref":"#/components/schemas/ConfigurationContractSpec"}},"resource_ids":{"type":"array","default":null,"description":"Optional list of resource composite ids (`<resource_id>|<catalog_sku_org_id>|<catalog_sku_id>`, the same form returned as `id` on resource-SKU responses) to scope the generated plan to specific resources. When non-empty, the plan's coverage is restricted to these resources and the plan is created as an infrastructure plan — line items only attempt to cover the listed resources rather than the whole segment. Mutually exclusive with `renewal_commitment_ids` (a plan can be scoped by resources OR scoped by renewing commitments, not both). Usually omitted; supply only when the user has explicitly named the resources to cover. Templates do not accept this field — supplying it on a template create/update is rejected.","items":{},"nullable":true},"renewal_commitment_ids":{"type":"array","default":null,"description":"Optional list of expiring commitment ids the plan is renewing. When non-empty, the plan is a renewal: coverage is built from the source commitments' historical usage, and each generated line item carries a `renewal_commitment_id` linking back to the source it proposes to replace. Mutually exclusive with `resource_ids`. On a renewal plan PUT this re-targets which commitments are being renewed (recalc); on a non-renewal plan PUT, sending this is rejected (use the dedicated POST /commitment-plans/renewals to create a renewal). Read-back unchanged from a GET so the configuration round-trips through PUT.","items":{"type":"string","format":"uuid"},"nullable":true}},"required":["contract_specs"],"additionalProperties":false},"ConfigurationContractSpec":{"type":"object","properties":{"commitment_type":{"type":"string","description":"Commitment type identifier — e.g. 'aws/savingsplan/Compute', 'aws/AmazonEC2', 'aws/AmazonRDS'. Values are provider-prefixed; fetch the exact list from GET /commitment-types and pass through verbatim. Rejected with 422 if the identifier is unknown across all providers; the validator does not enforce that the type belongs to the request's `provider` (a mismatched-but-real type will pass schema validation and produce a plan with no line items)."},"contract_term":{"description":"Commitment term (e.g. 'thirty_day_gris', 'one_year_gris', 'one_year', 'three_year'). Validated against the catalog entry for the supplied commitment_type — invalid (type, term) pairs are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["one_year_gris","thirty_day_gris","two_month_gris","three_month_gris","four_month_gris","five_month_gris","six_month_gris","seven_month_gris","eight_month_gris","nine_month_gris","ten_month_gris","eleven_month_gris","twelve_month_gris","thirteen_month_gris","fourteen_month_gris","fifteen_month_gris","sixteen_month_gris","seventeen_month_gris","eighteen_month_gris","nineteen_month_gris","twenty_month_gris","twenty_one_month_gris","twenty_two_month_gris","twenty_three_month_gris","twenty_four_month_gris","twenty_five_month_gris","twenty_six_month_gris","twenty_seven_month_gris","twenty_eight_month_gris","twenty_nine_month_gris","thirty_month_gris","thirty_one_month_gris","thirty_two_month_gris","thirty_three_month_gris","thirty_four_month_gris","thirty_five_month_gris","one_year","two_year","three_year","five_year","zero_day","thirty_day","two_month","three_month","four_month","five_month","six_month","seven_month","eight_month","nine_month","ten_month","eleven_month","thirteen_month","fourteen_month","fifteen_month","sixteen_month","seventeen_month","eighteen_month","nineteen_month","twenty_month","twenty_one_month","twenty_two_month","twenty_three_month","twenty_five_month","twenty_six_month","twenty_seven_month","twenty_eight_month","twenty_nine_month","thirty_month","thirty_one_month","thirty_two_month","thirty_three_month","thirty_four_month","thirty_five_month"]},"payment_option":{"description":"Payment option (e.g. 'no_upfront', 'partial_upfront', 'all_upfront'). Validated against the catalog entry for the supplied (commitment_type, contract_term) pair — invalid triples are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["no_upfront","partial_upfront","all_upfront"]}},"required":["commitment_type","contract_term","payment_option"],"additionalProperties":false},"AutoPurchase":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the schedule is currently active"},"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","description":"Dollar floor on projected monthly savings — plans that don't clear this are skipped even when the schedule fires."},"start_date":{"type":"string","format":"date","description":"Earliest date the automation may fire (inclusive). Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","description":"Latest date the automation may fire (inclusive). Null = no upper bound.","nullable":true},"next_execution_date":{"type":"string","format":"date","description":"When the next automated run is scheduled (computed)"},"last_executed_at":{"type":"string","format":"date-time","description":"When the last automated run fired, or null if it has not yet","nullable":true}},"required":["enabled","end_date","min_monthly_savings","schedule","start_date"],"additionalProperties":false},"ApiErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"detail":{"nullable":true},"code":{"type":"string","nullable":true},"url":{"type":"string","nullable":true},"timestamp":{"type":"string"},"type":{"type":"string"}},"required":["message","timestamp","type"]},"Error":{"type":"object","properties":{"code":{"type":"integer","description":"Error code"},"status":{"type":"string","description":"Error name"},"message":{"type":"string","description":"Error message"},"errors":{"type":"object","description":"Errors","additionalProperties":{}}},"additionalProperties":false}},"responses":{"DEFAULT_ERROR":{"description":"Default error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}
```

## Update a commitment plan template

> Merge-semantic update: only keys present in the body are applied. Pass \`auto\_purchase: null\` to clear an existing schedule; omit the key to leave it untouched. System-generated templates can have their \`auto\_purchase\` schedule edited but not their \`name\` or \`configuration\`.

```json
{"openapi":"3.0.2","info":{"title":"Archera.ai Beta API","version":"v1.0.0"},"tags":[{"name":"Commitment Plan Templates (Beta)","description":"Agent-friendly commitment plan template endpoints"}],"paths":{"/beta/v1/org/{org_id}/commitment-plan-templates/{template_id}":{"put":{"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitmentPlanTemplate"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not Found"},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"$ref":"#/components/responses/UNPROCESSABLE_CONTENT"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"default":{"$ref":"#/components/responses/DEFAULT_ERROR"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCommitmentPlanTemplateArgs"}}}},"tags":["Commitment Plan Templates (Beta)"],"summary":"Update a commitment plan template","description":"Merge-semantic update: only keys present in the body are applied. Pass `auto_purchase: null` to clear an existing schedule; omit the key to leave it untouched. System-generated templates can have their `auto_purchase` schedule edited but not their `name` or `configuration`."}}},"components":{"schemas":{"CommitmentPlanTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique template identifier"},"name":{"type":"string","description":"Human-readable template name"},"segment_id":{"type":"string","format":"uuid","description":"Segment this template generates plans for"},"created_at":{"type":"string","format":"date-time","description":"When the template was created"},"is_system_generated":{"type":"boolean","description":"True if this template was created automatically by the system — the three built-ins that back Recommended / Balanced / High Savings. Describes origin, not role — system-generated templates are immutable."},"configuration":{"description":"The inputs that plans generated from this template will use","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"description":"Scheduled auto-purchase settings, or null if the template is not on a schedule.","anyOf":[{"$ref":"#/components/schemas/AutoPurchase"},{"type":"object","nullable":true}]}},"required":["auto_purchase","configuration","created_at","id","is_system_generated","name","segment_id"],"additionalProperties":false},"CommitmentPlanConfiguration":{"type":"object","properties":{"max_upfront_cost":{"type":"number","default":0,"description":"Cap on the one-time upfront dollars the generated plan is allowed to include. Defaults to 0 — the recommender excludes any line item with an upfront cost. Pass null to lift the cap entirely. Otherwise, line items with upfront costs are excluded if adding them would exceed the cap.","nullable":true},"lookback_days":{"type":"integer","default":null,"description":"How many days of historical usage to feed into plan generation. Defaults to 7 when omitted — matches the recommender's default and gives a representative recent-week baseline. Increase for workloads with weekly/seasonal variance. NULL on renewal plans: renewals derive their usage window from the source commitments' end dates, so this field has no effect. Sending a non-null value to a renewal plan PUT is rejected so round-tripping is honest.","nullable":true},"contract_specs":{"description":"List of contract specs to consider when generating the plan. Each spec is a triple of (commitment_type, contract_term, payment_option). The plan generator will pick the best mix of offerings matching these specs.","type":"array","items":{"$ref":"#/components/schemas/ConfigurationContractSpec"}},"resource_ids":{"type":"array","default":null,"description":"Optional list of resource composite ids (`<resource_id>|<catalog_sku_org_id>|<catalog_sku_id>`, the same form returned as `id` on resource-SKU responses) to scope the generated plan to specific resources. When non-empty, the plan's coverage is restricted to these resources and the plan is created as an infrastructure plan — line items only attempt to cover the listed resources rather than the whole segment. Mutually exclusive with `renewal_commitment_ids` (a plan can be scoped by resources OR scoped by renewing commitments, not both). Usually omitted; supply only when the user has explicitly named the resources to cover. Templates do not accept this field — supplying it on a template create/update is rejected.","items":{},"nullable":true},"renewal_commitment_ids":{"type":"array","default":null,"description":"Optional list of expiring commitment ids the plan is renewing. When non-empty, the plan is a renewal: coverage is built from the source commitments' historical usage, and each generated line item carries a `renewal_commitment_id` linking back to the source it proposes to replace. Mutually exclusive with `resource_ids`. On a renewal plan PUT this re-targets which commitments are being renewed (recalc); on a non-renewal plan PUT, sending this is rejected (use the dedicated POST /commitment-plans/renewals to create a renewal). Read-back unchanged from a GET so the configuration round-trips through PUT.","items":{"type":"string","format":"uuid"},"nullable":true}},"required":["contract_specs"],"additionalProperties":false},"ConfigurationContractSpec":{"type":"object","properties":{"commitment_type":{"type":"string","description":"Commitment type identifier — e.g. 'aws/savingsplan/Compute', 'aws/AmazonEC2', 'aws/AmazonRDS'. Values are provider-prefixed; fetch the exact list from GET /commitment-types and pass through verbatim. Rejected with 422 if the identifier is unknown across all providers; the validator does not enforce that the type belongs to the request's `provider` (a mismatched-but-real type will pass schema validation and produce a plan with no line items)."},"contract_term":{"description":"Commitment term (e.g. 'thirty_day_gris', 'one_year_gris', 'one_year', 'three_year'). Validated against the catalog entry for the supplied commitment_type — invalid (type, term) pairs are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["one_year_gris","thirty_day_gris","two_month_gris","three_month_gris","four_month_gris","five_month_gris","six_month_gris","seven_month_gris","eight_month_gris","nine_month_gris","ten_month_gris","eleven_month_gris","twelve_month_gris","thirteen_month_gris","fourteen_month_gris","fifteen_month_gris","sixteen_month_gris","seventeen_month_gris","eighteen_month_gris","nineteen_month_gris","twenty_month_gris","twenty_one_month_gris","twenty_two_month_gris","twenty_three_month_gris","twenty_four_month_gris","twenty_five_month_gris","twenty_six_month_gris","twenty_seven_month_gris","twenty_eight_month_gris","twenty_nine_month_gris","thirty_month_gris","thirty_one_month_gris","thirty_two_month_gris","thirty_three_month_gris","thirty_four_month_gris","thirty_five_month_gris","one_year","two_year","three_year","five_year","zero_day","thirty_day","two_month","three_month","four_month","five_month","six_month","seven_month","eight_month","nine_month","ten_month","eleven_month","thirteen_month","fourteen_month","fifteen_month","sixteen_month","seventeen_month","eighteen_month","nineteen_month","twenty_month","twenty_one_month","twenty_two_month","twenty_three_month","twenty_five_month","twenty_six_month","twenty_seven_month","twenty_eight_month","twenty_nine_month","thirty_month","thirty_one_month","thirty_two_month","thirty_three_month","thirty_four_month","thirty_five_month"]},"payment_option":{"description":"Payment option (e.g. 'no_upfront', 'partial_upfront', 'all_upfront'). Validated against the catalog entry for the supplied (commitment_type, contract_term) pair — invalid triples are rejected with 422. Validation is cross-provider (see `commitment_type`).","type":"string","enum":["no_upfront","partial_upfront","all_upfront"]}},"required":["commitment_type","contract_term","payment_option"],"additionalProperties":false},"AutoPurchase":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the schedule is currently active"},"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","description":"Dollar floor on projected monthly savings — plans that don't clear this are skipped even when the schedule fires."},"start_date":{"type":"string","format":"date","description":"Earliest date the automation may fire (inclusive). Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","description":"Latest date the automation may fire (inclusive). Null = no upper bound.","nullable":true},"next_execution_date":{"type":"string","format":"date","description":"When the next automated run is scheduled (computed)"},"last_executed_at":{"type":"string","format":"date-time","description":"When the last automated run fired, or null if it has not yet","nullable":true}},"required":["enabled","end_date","min_monthly_savings","schedule","start_date"],"additionalProperties":false},"ApiErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"detail":{"nullable":true},"code":{"type":"string","nullable":true},"url":{"type":"string","nullable":true},"timestamp":{"type":"string"},"type":{"type":"string"}},"required":["message","timestamp","type"]},"Error":{"type":"object","properties":{"code":{"type":"integer","description":"Error code"},"status":{"type":"string","description":"Error name"},"message":{"type":"string","description":"Error message"},"errors":{"type":"object","description":"Errors","additionalProperties":{}}},"additionalProperties":false},"UpdateCommitmentPlanTemplateArgs":{"type":"object","properties":{"name":{"type":"string","description":"New template name"},"configuration":{"description":"Replacement configuration","allOf":[{"$ref":"#/components/schemas/CommitmentPlanConfiguration"}]},"auto_purchase":{"description":"Replacement schedule. Pass null to clear an existing schedule. Omit the key to leave the schedule untouched.","anyOf":[{"$ref":"#/components/schemas/CreateAutoPurchase"},{"type":"object","nullable":true}]}},"additionalProperties":false},"CreateAutoPurchase":{"type":"object","properties":{"schedule":{"type":"string","enum":["daily","weekly","monthly"],"description":"Cadence: 'daily', 'weekly', or 'monthly'"},"min_monthly_savings":{"type":"number","default":0,"description":"Dollar floor on projected monthly savings"},"enabled":{"type":"boolean","default":true,"description":"Whether the schedule is active"},"start_date":{"type":"string","format":"date","default":null,"description":"Earliest date automation may fire. Null = no lower bound.","nullable":true},"end_date":{"type":"string","format":"date","default":null,"description":"Latest date automation may fire. Null = no upper bound.","nullable":true}},"required":["schedule"],"additionalProperties":false}},"responses":{"UNPROCESSABLE_CONTENT":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"DEFAULT_ERROR":{"description":"Default error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}
```

## Delete a commitment plan template

> Delete a template. System-generated templates cannot be deleted.

```json
{"openapi":"3.0.2","info":{"title":"Archera.ai Beta API","version":"v1.0.0"},"tags":[{"name":"Commitment Plan Templates (Beta)","description":"Agent-friendly commitment plan template endpoints"}],"paths":{"/beta/v1/org/{org_id}/commitment-plan-templates/{template_id}":{"delete":{"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not Found"},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"default":{"$ref":"#/components/responses/DEFAULT_ERROR"}},"tags":["Commitment Plan Templates (Beta)"],"summary":"Delete a commitment plan template","description":"Delete a template. System-generated templates cannot be deleted."}}},"components":{"schemas":{"ApiErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"detail":{"nullable":true},"code":{"type":"string","nullable":true},"url":{"type":"string","nullable":true},"timestamp":{"type":"string"},"type":{"type":"string"}},"required":["message","timestamp","type"]},"Error":{"type":"object","properties":{"code":{"type":"integer","description":"Error code"},"status":{"type":"string","description":"Error name"},"message":{"type":"string","description":"Error message"},"errors":{"type":"object","description":"Errors","additionalProperties":{}}},"additionalProperties":false}},"responses":{"DEFAULT_ERROR":{"description":"Default error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.archera.ai/api-reference/beta-api/commitment-plan-templates-beta.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
