Map API Entities to Terraform Resources
Entity Mapping
Add the x-speakeasy-entity extension to objects in your OpenAPI Specification document to include them as entities in the Terraform provider, such as managed resources. The extension value may be a single string or an array of strings if the object should be represented by multiple API entities.
As a component:
components:
schemas:
Order:
description: An order helps you make coffee
x-speakeasy-entity: Order
properties:
id:
type: integer
description: Numeric identifier of the order.
name:
type: string
description: Product name of the coffee.
price:
type: number
description: Suggested cost of the coffee.
required:
- name
- price
type: objectOr inline in a path:
paths:
/order:
post:
tags:
- Order
summary: Create a coffee order
x-speakeasy-entity-operation: Order#create
requestBody:
content:
application/json:
schema:
x-speakeasy-entity: Order
properties:
id:
type: integer
description: Numeric identifier of the order.
name:
type: string
description: Product name of the coffee.
price:
type: number
description: Suggested cost of the coffee.
required:
- name
- price
type: objectresource "yourprovider_order" "example" {
name = "Filter Blend"
price = 11.5
}Where you place the x-speakeasy-entity annotation affects the Terraform resource schema structure.
- At the top level: Properties are nested objects.
- At a lower level: Properties above the annotation are flattened.
Top Level
Pet:
x-speakeasy-entity: Order
type: object
properties:
data:
type: object
properties:
name:
type: string
# ...Results in the following resource schema and configuration:
resource "yourprovider_order" "example" {
data = {
name = "Filter Blend"
}
}Lower Level
Pet:
type: object
properties:
data:
x-speakeasy-entity: Order
type: object
properties:
name:
type: string
#...Results in the following resource schema and configuration:
resource "yourprovider_order" "example" {
name = "Filter Blend"
}Warning
Properties above the x-speakeasy-entity annotation are flattened, which could cause conflicts. Apply the annotation carefully to align the structure of the Terraform provider with the API’s intended interaction.
Specify CRUD Operations for API Endpoints
The x-speakeasy-entity-operation annotation specifies CRUD (create, read, update, and delete) operations associated with each endpoint in the OpenAPI spec for a Terraform entity. The value determines the behavior of operations such as create, read, update, and delete and is structured as Entity#operation,operation,...#order:
Entityrepresents the name of the entity.operationcan be one or more ofcreate,read,update, anddelete, concatenated with commas.orderis optional and can be used to define additional API calls that should be invoked for a given CRUD invocation.
Behavior of Operations
Entity#createmakes the entity a Terraform resource.Entity#readensures consistency with Terraform state, updates attributes, and generates a data source.Entity#updateprovides update support for the resource. Without it, any attribute change requires resource replacement (ForceNew).Entity#deleteenables deletion of the resource. Without it, no action is taken on deletion.Entity#create,update(idempotent operations) indicates the API is idempotent. Combine these operations to allow the same API call to create new objects and update existing ones, depending on attribute changes.
In this example, a Pet managed resource with full create, read, update, and delete lifecycle and Pet data resource (due to Pet#read) are defined:
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
x-speakeasy-entity-operation: Pet#create
/pet/{petId}:
get:
tags:
- pet
summary: Info for a specific pet
x-speakeasy-entity-operation: Pet#read
update:
tags:
- pet
summary: Update the pet
x-speakeasy-entity-operation: Pet#update
delete:
tags:
- pet
summary: Delete the pet
x-speakeasy-entity-operation: Pet#deleteNote
Terraform generation automatically handles pagination implementation details
via the x-speakeasy-pagination extension.
This includes paging through all responses and removing unnecessary pagination
handling properties from the schema.
In this example, an automatically paginated Pets data resource is defined:
paths:
/pet:
get:
tags:
- pet
summary: Lists all pets
x-speakeasy-entity-operation: Pets#read
x-speakeasy-pagination:
type: offsetLimit
inputs:
- name: page
in: parameters
type: page
outputs:
results: $.resultsMultiple API Operations for One Resource
When multiple API operations are necessary for a single resource, use the additional entity-ordering capabilities of the x-speakeasy-entity-operation annotation.
paths:
/pet/{petId}:
get:
x-speakeasy-entity-operation: Pet#read#1
/animal:
get:
x-speakeasy-entity-operation: Pet#read#2Multiple API operations for one resource can be combined with multiple entity operations of one API operation for multiple resources as necessary.
One API Operation for Multiple Resources
When a single API operation is necessary for multiple resources, use multiple entity operation entries with the x-speakeasy-entity-operation annotation.
parameters:
- in: query
name: id
required: false
schema:
type: string
operationId: GetAnimal
x-speakeasy-entity-operation:
- Cat#read
- Dog#readOne API operation for multiple resources can be combined with the entity operation ordering of multiple API operations for one resource as necessary.
Manual association between Operations and Resource / Data Sources
The default behavior within Speakeasy is to automatically infer a data source from all operations that have an x-speakeasy-entity-operation: Entity#read association defined.
For some APIs, you might want the data source to use a “search” endpoint (e.g., search for an entity by name, where name is non-unique), while using a “get” operation for the resource (e.g., to find an entity by ID for state reconciliation).
In this case, use an object syntax for the x-speakeasy-entity-operation annotation to explicitly control whether an operation generates a resource, a data source, or both:
paths:
"/example":
get:
operationId: getThing
x-speakeasy-entity-operation:
terraform-datasource: null
terraform-resource: Thing#readThis syntax allows you to:
- Prevent automatic generation of a data source by setting
terraform-datasourcetonull - Prevent invocation of the operation during the resource’s Read method (“invoked as part of terraform state refresh”) by setting
terraform-resourcetonull
For example, the configuration above declares that getThing is associated with just a resource, and a data source should not be automatically generated.
Wrapping Additional API Operation Response Data
When defining multiple API operations for a single entity, an API definition may be written such that those API operation response are a flattened object. When adding those additional operations to the entity, those flattened object properties are added to the top level of the resource schema by default.
Use x-speakeasy-wrapped-attribute extension to override this behavior, which will create a wrapping attribute that contains the underlying object properties in the final resource schema.
In this example, the resource will put the second API operation response properties underneath a subconfig attribute:
paths:
/example/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
get:
x-speakeasy-entity-operation: Example#read
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ExampleResponse'
/example/{id}/subconfig:
parameters:
- name: id
in: path
required: true
schema:
type: string
get:
x-speakeasy-entity-operation: Example#read#2
responses:
'200':
description: OK
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ExampleSubconfigResponse'
- x-speakeasy-wrapped-attribute: subconfigArray Response Wrapping
Terraform resources require an object-type root schema. When an API returns an array, Speakeasy automatically wraps it in an attribute (default name: data).
Default behavior:
paths:
/things:
get:
x-speakeasy-entity-operation: Things#read
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
x-speakeasy-entity: ThingsSince the response is type: array, Speakeasy wraps it in a data attribute for Terraform compatibility.
Access in Terraform:
data.my_things_list.data[0].idCustomize the wrapper name:
paths:
/things:
get:
x-speakeasy-entity-operation: Things#read
responses:
'200':
description: OK
content:
application/json:
schema:
x-speakeasy-wrapped-attribute: items
type: array
items:
x-speakeasy-entity: ThingsNow the wrapping attribute is named items instead:
data.my_things_list.items[0].idNote
The wrapping attribute name is a Terraform construct created by Speakeasy, completely separate from your API’s response structure. Use x-speakeasy-wrapped-attribute to customize it.
Resources with Soft Delete
By default, a generated managed resource uses the HTTP 404 Not Found status code on read to automatically remove the resource from the Terraform state which causes the next Terraform plan to propose recreating the resource. For resource APIs that support soft delete (grace time period before the resource is fully deleted), the x-speakeasy-soft-delete-property annotation adds a check against a read response property to also propose resource recreation.
For managed resources, any x-speakeasy-soft-delete-property attribute is omitted from the schema and state. For data resources, the attribute remains to preserve client-side filtering capabilities.
In this example, the resource will be proposed for recreation if the deleted_at property has a value:
paths:
"/example":
get:
x-speakeasy-entity-operation: Example#read
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schema/ExampleGetResponse"
components:
schemas:
ExampleGetResponse:
type: object
properties:
# ...
deleted_at:
type: string
format: date-time
x-speakeasy-soft-delete-property: trueLast updated on