Skip to main content

Provision Orbit resources with Terraform

The Orbit Terraform provider lets platform teams provision and version Orbit CPaaS resources as code in CI — the same way they manage the rest of their cloud estate. It is a thin wrapper over the official Orbit Go SDK: the provider configures one SDK client, and each resource maps Terraform plan/state onto the Orbit REST API through it.
Early access. The provider’s source lives in the Orbit monorepo. As with the Go SDK, a github.com/devotel/terraform-provider-orbit release and a registry publish are still pending, so terraform init cannot pull the released binary yet. Build from source until the registry listing ships; the replace directive in the provider’s go.mod builds it against the in-repo SDK (run go mod tidy once to populate go.sum).

1. Configure the provider

The provider needs an API key — a dv_live_sk_… key minted in the dashboard under Settings → API Keys. Supply it either inline or through the environment; the argument is marked sensitive, so it never lands in the Terraform console output or state diagnostics.
In CI, keep the key out of config entirely — set ORBIT_API_KEY in the pipeline’s secret store and drop the api_key argument from the provider block.

2. Resources

Six resources cover the Terraform-manageable surface. Every one supports terraform import <addr> <id>. Every resource follows the same template: the provider configures one SDK client, and each resource maps Terraform plan/state onto the REST API through it.

orbit_webhook_endpoint

orbit_number

Purchases a number from inventory (POST /numbers/purchase) and configures its inbound routing. phone_number and country_code force replacement; label, status, capabilities, forwarding_number, compliance_profile_id and tags are updated in place. Outbound termination is owned by the platform softswitch and is intentionally not configurable here.

orbit_messaging_service

Bundles a sender pool, opt-out list and delivery/throughput configuration for outbound SMS/MMS. mps_cap sets a messages-per-second throughput cap (omit for unbounded). Nullable attributes removed from config are cleared on the next apply.

orbit_subaccount

A child organization under the authenticated tenant with its own team-member ceiling, rate limit and opening credit balance. slug and initial_credits_cents force replacement. api_key is minted once at creation and exposed as a sensitive computed attribute — it is never read back.

orbit_campaign

A marketing campaign (blast / drip / journey). Campaigns are created in draft; sending is a runtime action and is not part of the declarative lifecycle.

orbit_agent

An AI agent — a named conversational assistant with a system prompt, model and generation settings. The resource manages the agent’s portable configuration; the tool registry, knowledge-base bindings and nested runtime config are managed through their own surfaces and are intentionally out of scope. type, status, model, temperature and max_tokens are server-defaulted when omitted.

3. Worked example: messaging service + webhook endpoint

This configuration purchases a number, wires a messaging service to it, and subscribes a webhook endpoint to delivery receipts:
Plan and apply:
apply prints the server-assigned ids. Bring pre-existing resources under management with terraform import:
After each import, run terraform plan — it diffs the imported state against your config, and any attribute the config omits shows as drift to reconcile.

4. Drift and import patterns

  • Import-then-diff. terraform import pulls the resource’s current server state into the state file; it does not write config for you. After import, copy the attribute values from terraform state show <addr> into your .tf files so the next plan is empty.
  • Replacement-forcing attributes. Changing a force-replacement attribute (orbit_number.phone_number, orbit_subaccount.slug, orbit_subaccount.initial_credits_cents) destroys and recreates the resource on the next apply. Review the plan before approving.
  • Clearing nullable attributes. On orbit_messaging_service, removing a nullable attribute from config clears it server-side on the next apply — the dashboard and Terraform stay in sync both directions.
  • Write-only secrets. orbit_webhook_endpoint.secret and orbit_subaccount.api_key are never read back from the API, so Terraform cannot detect out-of-band changes to them. Rotate them by updating the variable and re-applying.
  • Detect out-of-band edits. terraform plan with no local changes reports any attribute drifted since the last apply; run it on a schedule (or terraform plan -refresh-only) to catch dashboard-side edits.

5. What is intentionally not configurable

Outbound voice and SMS termination is owned by the platform softswitch — no Terraform resource can set an outbound carrier, SIP trunk, or messaging route, and none ever will. The same holds for the agent tool registry and knowledge-base bindings (managed through their own surfaces) and for campaign sending, which is a runtime action, not declarative configuration. Everything else in the six resources above is supported.

See also