> ## Documentation Index
> Fetch the complete documentation index at: https://code.dcycle.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Resend Commuting Survey

> Send the commuting survey again for a period, to named employees or to everyone who has not answered yet

[← Employees API](/api-reference/employees/overview)

Send the commuting survey again for a reporting period — either to a list of email addresses you name, or to every active employee who has not yet answered for that period.

<Warning>
  **Do not use `status` to find who has not answered.** The field is accepted and deprecated, and using it silently skips people who still need the reminder.

  `status` is the employee's **processing** status. It flips to `uploaded` the first time any period of theirs is processed and **never reverts**. So an employee who answered last quarter and has not answered this one still reads as `uploaded`, and filtering on it leaves them out of the send.

  Use `exclude_responded_period: true` instead. It is period-aware — it selects active employees with no response row for the `start_date`/`end_date` you asked about — and it takes precedence over `status` when both are sent.
</Warning>

## Request

### Headers

<ParamField header="x-organization-id" type="string" required>
  UUID of the organization whose employees you are contacting.

  **Format:** UUID
</ParamField>

<ParamField header="x-api-key" type="string">
  Your API key.
</ParamField>

### Body Parameters

<ParamField body="lang" type="string" required>
  Language the survey is sent in.

  **Accepted values:** `ar`, `ca`, `de`, `en`, `es`, `fr`, `it`, `pt`, `zh`
</ParamField>

<ParamField body="start_date" type="string" required>
  First day of the period the survey asks about.

  **Format:** `YYYY-MM-DD`
</ParamField>

<ParamField body="end_date" type="string" required>
  Last day of that period.

  **Format:** `YYYY-MM-DD`
</ParamField>

<ParamField body="emails" type="array[string]">
  Send to exactly these employees, by email address. When present this wins over every other selector — no "who has not answered" logic runs at all.

  Omit it to select recipients by rule instead.
</ParamField>

<ParamField body="exclude_responded_period" type="boolean" default="false">
  When `true`, send only to **active employees with no response for the requested period**. This is the correct way to chase non-respondents.

  Ignored when `emails` is present.
</ParamField>

<ParamField body="status" type="string" deprecated>
  **Deprecated.** Filters by the employee's processing status (`uploaded`, `loading`, `error`), which is not a valid proxy for "has not responded to this period" — see the warning above. `exclude_responded_period` takes precedence over it.
</ParamField>

<ParamField body="subject" type="string">
  Subject line for the email. Falls back to the platform default when omitted.
</ParamField>

<ParamField body="deadline" type="string">
  Date shown to the employee as the answering deadline.

  **Format:** `YYYY-MM-DD`
</ParamField>

<ParamField body="template_id" type="string">
  UUID of a survey template to use instead of the default one.

  **Format:** UUID
</ParamField>

<Note>
  **Recipient selection has a precedence order**, and only one branch runs:

  1. `emails` present → exactly those employees.
  2. Otherwise `exclude_responded_period: true` → active employees with no response for the period.
  3. Otherwise → the remaining selection, including the deprecated `status` filter.
</Note>

## Response

Returns `202 Accepted` with the employees that were **selected**, not with those that were actually mailed. The send happens in the background and skips anyone with no email address, so an employee can appear in this array and receive nothing. A `202` means "selection accepted", not "delivered".

<ResponseField name="array" type="array[object]">
  The employees selected by your filters. Each is a full employee object — the fields below are the ones that matter here, but the response carries every field of the employee read schema, not just these.

  <Expandable title="Employee Object">
    <ResponseField name="id" type="string">
      Employee UUID.
    </ResponseField>

    <ResponseField name="name" type="string | null">
      Employee name.
    </ResponseField>

    <ResponseField name="email" type="string | null">
      Email address the survey went to.
    </ResponseField>

    <ResponseField name="organization_id" type="string">
      Organization the employee belongs to.
    </ResponseField>

    <ResponseField name="status" type="string">
      Processing status — the same field deprecated as a filter above.
    </ResponseField>

    <ResponseField name="situation" type="string | null">
      Employment situation, e.g. whether the employee is terminated.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # Chase everyone who has not answered for Q1
  curl -X POST "https://api.dcycle.io/v1/employees/resend-survey" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "x-organization-id: YOUR_ORGANIZATION_ID" \
    -H "Content-Type: application/json" \
    -d '{
      "lang": "es",
      "start_date": "2026-01-01",
      "end_date": "2026-03-31",
      "exclude_responded_period": true,
      "deadline": "2026-04-15"
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  HEADERS = {
      "x-api-key": "YOUR_API_KEY",
      "x-organization-id": "YOUR_ORGANIZATION_ID",
  }

  # Period-aware: only those with no response for this quarter
  response = requests.post(
      "https://api.dcycle.io/v1/employees/resend-survey",
      headers=HEADERS,
      json={
          "lang": "es",
          "start_date": "2026-01-01",
          "end_date": "2026-03-31",
          "exclude_responded_period": True,
          "deadline": "2026-04-15",
      },
      timeout=30,
  )

  sent_to = response.json()
  print(f"queued for {len(sent_to)} employees")
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch(
    "https://api.dcycle.io/v1/employees/resend-survey",
    {
      method: "POST",
      headers: {
        "x-api-key": "YOUR_API_KEY",
        "x-organization-id": "YOUR_ORGANIZATION_ID",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        lang: "es",
        start_date: "2026-01-01",
        end_date: "2026-03-31",
        exclude_responded_period: true,
        deadline: "2026-04-15",
      }),
    },
  );

  const sentTo = await response.json();
  ```
</CodeGroup>

### Successful Response

Returns `202 Accepted`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
[
  {
    "id": "6b2d9e41-7a83-4c50-9f27-1e5b8d3a0c94",
    "name": "Ana Ruiz",
    "email": "ana.ruiz@example.com",
    "organization_id": "a8315ef3-dd50-43f8-b7ce-d839e68d51fa",
    "status": "uploaded",
    "situation": "active"
  }
]
```

An empty array means nobody matched — with `exclude_responded_period: true` that is the good outcome: everyone has already answered.

## Common Errors

### 422 Unprocessable Entity

**Cause:** `lang`, `start_date` or `end_date` is missing. All three are required, whichever way you select recipients.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": [
    {
      "loc": ["body", "lang"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

**Cause:** `lang` is not one of the nine accepted values.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": [
    {
      "loc": ["body", "lang"],
      "msg": "value is not a valid enumeration member; permitted: 'ar', 'ca', 'de', 'en', 'es', 'fr', 'it', 'pt', 'zh'",
      "type": "type_error.enum",
      "ctx": {
        "enum_values": ["ar", "ca", "de", "en", "es", "fr", "it", "pt", "zh"]
      }
    }
  ]
}
```

### 500 Internal Server Error

**Cause:** One of the addresses in `emails` is well formed but does not belong to any employee of this organization. The lookup finds nothing and the send fails on the missing employee, so the whole request errors — no survey goes out, not even to the addresses that did match.

A **malformed** address never gets this far: it is rejected with `422` by the email validator before any lookup happens. So `nobody@example` returns `422`, while `nobody@example.com` — valid syntax, unknown person — returns `500`.

Check your addresses against [List Employees](/api-reference/employees/list) first, and send only known ones.

## Use Cases

### Chase only the people who still owe you an answer

Send with `exclude_responded_period: true` and the period's dates. Employees who already answered that period are excluded, and — unlike the deprecated `status` filter — employees who answered a *previous* period are still included, because they genuinely have not answered this one.

### Re-send to a specific person

Pass `emails` with the single address. That branch skips every response check, so it works even for someone who already answered — useful when a reply was lost or the employee asks for the link again. Make sure the address belongs to an employee: a well-formed address that matches nobody fails the whole request with a `500`, and nothing is sent.

## Related Endpoints

<CardGroup cols={2}>
  <Card title="List Employees" icon="list" href="/api-reference/employees/list">
    Find the employees and their status
  </Card>

  <Card title="Create Employee" icon="plus" href="/api-reference/employees/create">
    Add the people who will receive the survey
  </Card>

  <Card title="Survey Templates" icon="file-lines" href="/api-reference/employees/survey-templates/overview">
    The templates `template_id` points at
  </Card>

  <Card title="Employees API" icon="users" href="/api-reference/employees/overview">
    Everything the Employees API covers
  </Card>
</CardGroup>
