Terraform provider
The Elido Terraform provider — terraform-provider-elido — lets you
manage short links the same way you manage the rest of your infra:
declaratively, in version control, with plan / apply semantics
and drift detection. None of our direct competitors (Bitly, TinyURL,
Rebrandly, Short.io, Dub.co) ship a Terraform provider — this is an
Elido-only capability.
The provider is a thin adapter over the public REST API. Anything
you can express in elido_link you can also express via the SDK or
a curl to api-core; Terraform just gives you a stable lifecycle
contract on top.
When to use it
- Marketing redirects belong with your infra. Cloudflare DNS, S3 lander, CloudFront distribution, and the short link that points at the lander all live in the same Terraform module. Delete the lander → the redirect goes with it.
- Bulk campaign links from a template. A
for_eachover channels × regions produces dozens of consistently-tagged links in oneterraform apply. - Multi-tenant onboarding. New tenant creation already runs
through Terraform → add an
elido_linkresource to the module and every tenant gets their branded redirects on day one.
If your only need is “create one link from a script”, reach for the
Go SDK or a curl. Terraform is for the case where you
want a lifecycle managed.
Status
v0.1.0 MVP. Surface today:
| Kind | Name | Endpoint |
|---|---|---|
| Resource | elido_link | POST /v1/workspaces/{id}/links (+ PATCH / DELETE) |
| Data source | elido_workspace | GET /v1/workspaces/{id} |
| Data source | elido_custom_domain | GET /v1/workspaces/{id}/domains (filtered locally) |
elido_custom_domain ships as read-only in v0.1.0 because
api-core does not yet proxy create/delete for custom domains —
register the domain in the dashboard first, then look it up here.
It becomes a full resource once the upstream API lands.
elido_folder and elido_api_key ship in v0.2.0. ADR-0034 has
the full deferred-work list.
Installation
The provider is not yet published on the Terraform Registry. Until
it is, install via dev_overrides:
git clone https://github.com/elidoapp/elido.git
cd elido/tools/terraform-provider-elido
make install-localThen add a dev_overrides block to ~/.terraformrc:
provider_installation {
dev_overrides {
"elidoapp/elido" = "/Users/<you>/.terraform.d/plugins/elidoapp/elido"
}
direct {}
}Under dev_overrides, terraform init is not required — plan
and apply resolve the binary directly.
Configure
terraform {
required_providers {
elido = {
source = "elidoapp/elido"
version = "~> 0.1"
}
}
}
provider "elido" {
# api_url defaults to https://api.elido.app
# api_token reads ELIDO_API_TOKEN
}export ELIDO_API_TOKEN=ek_...| Attribute | Env fallback | Default |
|---|---|---|
api_url | ELIDO_API_URL | https://api.elido.app |
api_token | ELIDO_API_TOKEN | required |
For self-hosted Elido point api_url at your api-core. Tokens are
created at /dashboard/settings/api-keys.
Your first link
data "elido_workspace" "main" {
id = 42
}
resource "elido_link" "spring_campaign" {
workspace_id = data.elido_workspace.main.id
domain_id = 1
slug = "spring-2026"
destination_url = "https://example.com/landing/spring"
title = "Spring 2026 email campaign"
tags = ["spring-2026", "email"]
redirect_status = 301
}terraform plan
terraform applyThe provider keys state by the numeric link id, so renaming the
Terraform resource label or changing the slug does not force
replacement — it issues a PATCH. Changing workspace_id or
domain_id does force replacement (the link belongs to a different
edge route).
Bulk links
locals {
channels = ["email", "twitter", "linkedin", "reddit", "hn"]
regions = ["us", "eu", "apac", "latam"]
}
resource "elido_link" "campaign_launch" {
for_each = {
for pair in setproduct(local.channels, local.regions) :
"${pair[0]}-${pair[1]}" => pair
}
workspace_id = data.elido_workspace.main.id
domain_id = 1
slug = "launch-${each.key}"
destination_url = "https://example.com/launch?ch=${each.value[0]}&r=${each.value[1]}"
tags = ["launch-2026", each.value[0], each.value[1]]
}20 links, one apply. Delete the block and terraform apply
removes them in one transaction.
Importing existing links
Already have links you want under Terraform management? Use the
<workspace_id>:<link_id> format:
terraform import elido_link.spring_campaign 42:7A subsequent terraform plan shows the drift between the live link
and your HCL — converge by either updating HCL to match or letting
apply push your HCL state to the API.
Reference
Resource — elido_link
| Attribute | Type | Required | Notes |
|---|---|---|---|
workspace_id | number | yes | Forces replacement on change. |
domain_id | number | yes | Forces replacement on change. |
slug | string | no | Auto-generated when empty. |
destination_url | string | yes | |
title | string | no | |
tags | list | no | Order significant in plan diff. |
redirect_status | number | no | 301 / 302 / 307 / 308. Default 302. |
show_splash | bool | no | |
status | string | no | active, paused, archived. Default active. |
id | string | computed | Numeric ID, formatted as string for TF stability. |
created_at | string | computed | RFC3339. |
updated_at | string | computed | RFC3339. |
Data source — elido_custom_domain
Look up a custom redirect domain by hostname inside a workspace. Use
the resulting id as domain_id in elido_link resources.
data "elido_custom_domain" "links" {
workspace_id = data.elido_workspace.main.id
hostname = "links.example.com"
}
resource "elido_link" "spring_campaign" {
workspace_id = data.elido_workspace.main.id
domain_id = data.elido_custom_domain.links.id
destination_url = "https://example.com/landing/spring"
slug = "spring-2026"
}| Attribute | Type | Required | Notes |
|---|---|---|---|
workspace_id | number | yes | Workspace that owns the domain. |
hostname | string | yes | FQDN; wildcards keep the *. prefix. |
id | number | computed | Pass to elido_link.domain_id. |
status | string | computed | pending, verified, active, failed. |
is_wildcard | bool | computed | |
verify_token | string | computed | Sensitive. Empty after verification. |
created_at | string | computed | |
verified_at | string | computed | |
failed_at | string | computed | |
fail_reason | string | computed |
Data source — elido_workspace
| Attribute | Type | Required | Notes |
|---|---|---|---|
id | number | yes | Lookup key. |
name | string | computed | |
slug | string | computed | |
plan_tier | string | computed | free, paid, business. |
created_at | string | computed | |
updated_at | string | computed |
Where to file issues
Bugs, schema gaps, or “I want resource X” — open an issue at
github.com/elidoapp/elido with
the area:terraform label.