---
title: "Resend an invite"
method: POST
path: "/tenants/{id}/invites/{invite_id}/resend"
tags: ["invites"]
---

# Resend an invite

`POST /tenants/{id}/invites/{invite_id}/resend`

## Request

- Base URL: `https://api.instruxi.dev/api/v1/enforcer`
- URL: `https://api.instruxi.dev/api/v1/enforcer/tenants/{id}/invites/{invite_id}/resend`
- Auth: one of:
  - API key in header `Authorization`
  - API key in header `X-API-Key`

Reissues a pending invite: a fresh token and expiry, and the invite email again, preserving role, groups and inviter. Same permission as creating an invite (tenant membership); a member without tenant authority may only resend invites they sent. 409 invite_not_pending if the invite was accepted or cancelled. 403 `verified_email_required` when the caller signed up with only a passkey and has not verified an email yet.

## Path parameters

- `id` string, required
- `invite_id` string, required

## Response `200`

OK

- EnforcerV3InternalDomainInviteInvite
  - `accepted_account_id` string
  - `accepted_at` string
  - `created_at` string
  - `email` string: Email is the invited inbox. Empty on wallet-only invites (SIWE agents).
  - `expires_at` string
  - `group_ids` string[]: GroupIDs are the groups the invitee is added to on acceptance (0..20).
  - `groups` EnforcerV3InternalDomainInviteGroupRef[]: Groups is GroupIDs with names resolved (live groups only); read-side only.
    - `id` string
    - `name` string
  - `id` string
  - `invited_by` string
  - `role` EnforcerV3InternalDomainRoleRole
    - `admin_managed` boolean
    - `created_at` string
    - `cross_tenant` boolean: Capability grants (additive; all false = baseline-only, like "user").
    - `description` string
    - `id` string
    - `mpp_ops` boolean: MPPOps: read-only MPP deposit-intent operator views (migration 000129).
    - `name` string
    - `slug` string
    - `tenant_manage` boolean
    - `tenant_read` boolean
    - `tenant_write` boolean
    - `updated_at` string
  - `role_id` string
  - `status` string
  - `tenant` EnforcerV3InternalDomainTenantTenant
    - `account_abstraction` boolean
    - `allow_user_discovery` boolean: AllowUserDiscovery gates contact discovery for the whole tenant: when true, accounts may be discoverable (and new accounts default to discoverable); when false, discovery is off tenant-wide regardless of account.is_discoverable.
    - `app_url` string
    - `auth_provider` string: AuthProvider / WalletProvider: nil = inherit the instance default.
    - `banner_url` string
    - `billing_status` string: BillingStatus is the tenant's platform-billing dunning state, PROJECTED from enforcer-billing (migration 000087): "" | active | past_due | restricted | suspended | collections. enforcer-billing is the source of truth; this is a copy the billing.status_changed consumer keeps current so the value rides Accessor.billing_status on every resolve with no hop. "" means UNKNOWN and readers MUST treat it as active (fail open). `<-:false` makes GORM never write these two columns: Repository.Update is a whole-row Save, so without it an admin editing the tenant's name from a stale struct would silently roll the projection back. Only BillingStatusStore.ApplyBillingStatus writes them, by targeted UPDATE under the monotonic entered_at guard.
    - `billing_status_entered_at` string
    - `code` string
    - `code_expires_at` string: CodeExpiresAt is when the join code stops working everywhere a code is accepted, signing in and joining alike, as if it had been rotated away. Absent: the code never expires. Set by POST /tenants/{id}/code.
    - `created_at` string
    - `description` string
    - `id` string
    - `logo_url` string
    - `metadata` EnforcerV3InternalDomainTenantJSONBMap
    - `metered_sends_enabled` boolean: MeteredSendsEnabled turns on per-transaction limit metering: every value leg leaving the platform is measured against the caller's live cap before the server co-signs. Meaningful only while Web3Enabled is true — the pair (false, true) is refused on write; see ValidateWeb3Gates.
    - `modules` string[]: Modules is the tenant's MODULE entitlements as group slugs, prefixed `module_` (migration 000094, V3-02). Which HALO-Lego surfaces this tenant has bought — NOT which of them any given account may use, which is the role's question. It lives on the tenant rather than in account_groups because it is a fact about the TENANT: a module per account would mean auto-joining every new account and would make "remove one person from a module the tenant paid for" expressible. The resolver UNIONS this into Accessor.GroupSlugs, so every leaf's RequireModule reads it with no new field and no extra hop. Same `<-:false` guard and the same targeted-write rule as BillingStatus above: Repository.Update is a whole-row Save, so without it an admin editing the tenant's name from a stale struct would silently revoke every module. Only ModuleStore writes these two columns.
    - `modules_updated_at` string
    - `name` string
    - `payment_link_url` string
    - `privy_app_id` string
    - `self_join_policy` 'open' | 'invite_only'
    - `status` 'active' | 'inactive' | 'suspended'
    - `theme_colors` EnforcerV3InternalDomainTenantJSONBMap
    - `thumbnail_url` string
    - `updated_at` string
    - `wallet_provider` string
    - `web3_enabled` boolean: Web3Enabled is the tenant-wide web3 kill switch. False rejects EVERY web3 transaction for the tenant — guarded sends, signing, and RPC writes alike — so it is deliberately a gate rather than an enforcement mode. Defaults true (migration 000066) because false would disable web3 for every existing tenant on deploy.
  - `tenant_id` string
  - `updated_at` string
  - `wallet_address` string: WalletAddress is the invited EVM address, stored lowercase. Empty on email-only invites. Exactly one of Email / WalletAddress is set.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict

---

[API](https://skmtc.dev/instruxi/apis/enforcer-api.md) · [All operations](https://skmtc.dev/instruxi/apis/enforcer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/instruxi/apis/enforcer-api/revisions/fa82bc1becc0?raw)
