---
title: "Send a test invocation"
method: POST
path: "/functions/{id}/test"
tags: ["Functions"]
---

# Send a test invocation

`POST /functions/{id}/test`

Sends a real test email from a Primitive-controlled sender to a
local-part on one of the org's verified inbound domains. By
default the recipient is a synthetic
`__primitive_function_test+<random>@<domain>` address on a
domain selected to route to the function. Scoped functions use
their scoped domain; fallback functions use a domain that has
no enabled domain-scoped endpoint. Pass `local_part` to
override and exercise routing logic that branches on a specific
recipient (the common pattern when one function handles multiple
inboxes like `summarize@` and `action@`). The function fires
through the normal MX delivery path, so reply / send-mail calls
from inside the handler against the inbound's `email.id` work
the same as in production. Returns immediately after the send is
queued; the invocation appears on the function's invocations
list within a few seconds.

Requires that the function is currently `deployed`. Returns 422
if the function is in `pending` or `failed` state, or if the
org has no verified inbound domain to receive the test mail.
Returns 400 if `local_part` is set to a value that does not
match the local-part character set.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `local_part` string — Override the synthetic local-part. When set, the test email is sent to `<local_part>@<picked-domain>` instead of the default `__primitive_function_test+<random>@<picked-domain>`. Must start with an alphanumeric and contain only letters, digits, dots, plus signs, hyphens, or underscores; 1-64 characters total.

## Response `200`

Test send queued

- object
  - `success` true, required
  - `data` object, required — Metadata returned by POST /functions/{id}/test. The send is queued; poll `trace_url` to watch the run progress through send -> inbound -> webhook deliveries -> outbound requests, logs, and replies.
    - `test_run_id` string, uuid, required — Durable test run id used to fetch the run trace.
    - `inbound_domain` string, required — Verified inbound domain the test email was sent to.
    - `to` string, required — Synthetic local-part plus inbound_domain. Visible in the org's inbox.
    - `from` string, required — Primitive-controlled outbound sender used for the test.
    - `send_id` string, required — Outbound message id from the underlying send. NOT the inbound email's id; the inbound id is created when the email arrives via MX and lands on the function's invocations list.
    - `subject` string, required — Subject placed on the test email so it can be located in the inbox.
    - `poll_since` string, date-time, required — ISO timestamp suitable as a `since` lower bound when polling /emails for the inbound's arrival. Captured slightly before the send to absorb light clock skew.
    - `watch_url` string, uri, required — Function detail page where invocations show up live.
    - `trace_url` string, required — Relative API URL for GET /functions/{id}/test-runs/{test_run_id}/trace.

## Other responses

- `400` — Invalid request parameters
- `401` — Invalid or missing API key
- `404` — Resource not found
- `422` — The request was well-formed but could not be processed. For Payments this covers a missing payout address, a failed payment verification, a spend-policy decline, or an expired challenge; `error.code` distinguishes them.
- `502` — Primitive could not complete the downstream SMTP request
- `503` — Primitive is temporarily unable to process the request

---

[API](https://skmtc.dev/primitive/apis/primitive-api.md) · [All operations](https://skmtc.dev/primitive/apis/primitive-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/primitive/primitive-api/revisions/c2299d28022c/schema)
