# Forms Client

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /client/forms/{name}

**Open a form (customer)**

`operationId: CrmFormClientController_getForm`

The customer-facing twin of `GET /crm/form/{name}`: same gates and same reply. A signed-in customer is taken from the token (never from the request), which satisfies a `password` form and is the submitter.

#### Signature

```http
GET /client/forms/{name} (name: string, code?: string, email?: string, token?: string) -> As `GET /crm/form/{name}`
```

#### Access

Public — no credentials required.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | FORM_NOT_FOUND | No form or collection found with name <name> | No crm_form and no collection by that name (a form bound to a missing collection: "Collection not found"). | — |
| `403` | NOT_PUBLIC | This form is not available for public access | An explicit `read` list leaves out Guest (a collection: "This collection is not shared publicly"). | — |
| `401` | CODE_REQUIRED | This form needs an access code. | accessMode `code` with no code, or `participants` with no code ("This form is by invitation. Open it from the link you were sent."). Body `reason: "code-required"`. | — |

Plus the standard platform errors: `429`, `500`.

#### See also

- `GET /crm/form/{name}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Form name. |
| `code` | query | string | — |  |
| `x-form-code` | header | string | — |  |
| `email` | query | string | — |  |
| `token` | query | string | — |  |
| `x-form-token` | header | string | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | As `GET /crm/form/{name}` |
| `401` | This form needs an access code. — accessMode `code` with no code, or `participants` with no code ("This form is by invitation. Open it from the link you were sent."). Body `reason: "code-required"`. |
| `403` | This form is not available for public access — An explicit `read` list leaves out Guest (a collection: "This collection is not shared publicly"). |
| `404` | No form or collection found with name <name> — No crm_form and no collection by that name (a form bound to a missing collection: "Collection not found"). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /client/forms/{name}/access

**Ask for a form link or code (customer)**

`operationId: CrmFormClientController_requestAccess`

Same as `POST /crm/form/{name}/access`.

#### Signature

```http
POST /client/forms/{name}/access (name: string, body) -> { sent: true, email, via, session }
```

#### Access

Public — no credentials required.

#### Errors

Plus the standard platform errors: `429`, `500`.

#### See also

- `POST /crm/form/{name}/access`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Form name. |

### Request body

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { sent: true, email, via, session } |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /client/forms/{name}/submit

**Submit a form (customer)**

`operationId: CrmFormClientController_submit`

Same as `POST /crm/form/submit/{name}/{email}`, with the submitter email as `?email=` instead of a path segment.

#### Signature

```http
POST /client/forms/{name}/submit (name: string, email?: string, code?: string, token?: string, body) -> The saved submission
```

#### Access

Public — no credentials required.

#### Errors

Plus the standard platform errors: `429`, `500`.

#### See also

- `POST /crm/form/submit/{name}/{email}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `name` | path | string | yes | Form name. |
| `email` | query | string | — |  |
| `code` | query | string | — |  |
| `token` | query | string | — |  |

### Request body

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The saved submission |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

