Invites

Resend an invite email

Sends the invitation email again for an existing pending invite.

POST/invites/{id}/resend

Sends the invitation email again for an existing pending invite. Takes no request body and returns 200, not 201 - nothing new is created. The invite keeps its original id, token and expiresAt; resending does not extend the 3-day expiry, so an invite that has run out cannot be revived by resending it.

Once an invite expires the endpoint returns 409 invite.expired - revoke it and POST /members again to send a fresh link.

The returned Invite always has role: null on this endpoint, because the controller does not re-resolve the role. Read the role from GET /invites if you need it. resendCount counts operator resends only. lastResendAt is the last time any email went out for this invite, so it also moves when the automatic expiry reminder is sent 24 hours before expiresAt. Emits member.invite_resent.

Requires the members:write scope.

curl --request POST \
  --url 'https://api.envless.cloud/invites/<id>/resend' \
  --header 'Authorization: Bearer ev_sk_xxxxxxxxxxxx'
Try itPOSThttps://api.envless.cloud/invites/{id}/resend
Path parameters

Authorization

  • Authorizationstringrequiredheader

    Bearer token: an Envless API key (ev_sk_…), created in the dashboard or with POST /keys. The key is bound to one workspace; every request runs inside it.

Path parameters

  • idstringrequired

    Invite id from GET /invites.

Responses

200OK

Resend an invite email succeeded.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errornullrequired
  • dataobjectrequired
    Show child attributesHide child attributes
    • idstringrequired
    • emailstringrequired
    • statusenum<string>required

      Options: "pending", "expired"

    • roleobject | null
      Show child attributesHide child attributes
      • idstring
      • namestring
      • isSystemboolean
    • resendCountinteger
    • lastResendAtstring | nulldate-time
    • expiresAtstring | nulldate-time
    • sentAtstringrequireddate-time
  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": true,
    "code": 200,
    "message": "OK",
    "error": null,
    "data": {
        "id": "<string>",
        "email": "<string>",
        "status": "pending",
        "role": {
            "id": "<string>",
            "name": "<string>",
            "isSystem": true
        },
        "resendCount": 1,
        "lastResendAt": "2026-05-30T10:14:22.000Z",
        "expiresAt": "2026-05-30T10:14:22.000Z",
        "sentAt": "2026-05-30T10:14:22.000Z"
    },
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

Error envelope

Every failure below returns the same shape with success: false; branch on error.code, never on message.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errorobjectrequired

    Machine-readable failure detail. Null on success.

    Show child attributesHide child attributes
    • codeenum<string>required

      Stable error code. Branch on this, never on message.

      Options: "auth.api_key_required", "auth.api_key_not_found", "auth.api_key_user_missing", "auth.api_key_owner_not_member", "auth.scope_missing", "auth.scope_ceiling_exceeded", "auth.key_project_restricted", "auth.product_restricted", "auth.permission_denied", "auth.self_mutation_forbidden", "auth.step_up_required", "auth.step_up_fresh_required", "auth.cli_token_not_accepted", "auth.two_factor_required", "auth.workspace_two_factor_required", "auth.two_factor_invalid", "auth.two_factor_replayed", "auth.two_factor_locked", "auth.two_factor_not_enabled", "auth.two_factor_already_enabled", "request.body_must_be_json", "request.body_invalid", "request.body_too_large", "request.rate_limited", "request.invalid_pagination", "workspace.not_found", "workspace.slug_conflict", "workspace.limit_reached", "workspace.delete_last", "workspace.delete_too_early", "workspace.delete_has_projects", "domain.not_configured", "domain.not_found", "domain.invalid", "domain.taken", "domain.attempt_limit", "product.not_found", "product.slug_conflict", "product.locked", "project.not_found", "project.ambiguous_product", "project.slug_conflict", "environment.not_found", "environment.slug_conflict", "environment.expose_disabled", "environment.expose_private_product", "variable.not_found", "variable.name_conflict", "variable.ciphertext_invalid", "variable.baseline_drifted", "version.not_found", "member.not_found", "member.already_exists", "member.self_invite", "member.self_mutation", "member.owner_immutable", "member.owner_cannot_leave", "member.seat_limit", "invite.already_pending", "role.owner_not_assignable", "role.limit_reached", "role.immutable", "role.in_use", "invite.not_found", "invite.expired", "role.not_found", "role.name_conflict", "key.not_found", "key.limit_reached", "webhook.not_found", "webhook.delivery_not_found", "plan.limit_reached", "plan.upgrade_required", "request.not_found", "request.method_not_allowed", "request.conflict", "auth.unauthorized", "auth.forbidden", "request.invalid", "server.error"

    • resourcestring

      The resource or scope the failure relates to.

    • fieldstring

      The request field that caused the failure.

  • dataobject | nullrequired

    Null on most failures. A plan limit carries { limit, current }.

  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": false,
    "code": 401,
    "message": "Something went wrong.",
    "error": {
        "code": "auth.api_key_required",
        "resource": "<string>",
        "field": "<string>"
    },
    "data": {},
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

401Unauthorized

  • auth.api_key_required - the Authorization header is missing, or its value does not start with ev_sk_.
  • auth.api_key_not_found - the key is unknown, inactive or revoked.
  • auth.api_key_user_missing - the key is valid but its owner no longer exists.
  • auth.api_key_owner_not_member - the key's owner is no longer a member of the key's workspace.

403Forbidden

  • auth.workspace_two_factor_required - the workspace requires two-factor authentication and the key's owner has not turned it on.
  • auth.scope_missing - the key lacks a scope this operation requires; error.resource names it.

404Not Found

invite.not_found - no pending invite with that id exists in this workspace; a 404 with workspace.not_found is returned instead if the workspace itself has been soft-deleted.

409Conflict

invite.expired - the invite is past its expiresAt; resending cannot extend it, so revoke it and invite the address again.

500Internal Server Error

server.error - the email could not be sent; the resend bookkeeping is rolled back, so the invite is left exactly as it was.

503Service Unavailable

server.error - the API is in maintenance mode or is missing its configuration; retry with backoff.