# Connect

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /connect/webhook/{vendor}/{serviceId}

**Partner webhook (GET)**

`operationId: ConnectController_connectPartnerGet`

The GET form, for vendors that verify a webhook endpoint with a challenge request before sending real events. Same unauthenticated, query-scoped shape as the POST form.

#### Signature

```http
GET /connect/webhook/{vendor}/{serviceId} (vendor: string, serviceId: string, orgid?: string) -> The challenge response
```

#### Access

Public — no credentials required.

#### Notes

- Unauthenticated.

#### Errors

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

#### See also

- `POST /connect/webhook/{vendor}/{serviceId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | query | string | yes |  |
| `vendor` | path | string | yes | Partner name. |
| `serviceId` | path | string | yes | Optional. |
| `orgid` | header | string | — | Organization ID |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The challenge response |
| `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 /connect/webhook/{vendor}/{serviceId}

**Partner webhook (POST)**

`operationId: ConnectController_connectPartnerPost`

Receives a webhook from a partner service. **Unauthenticated** — it has to be, since the partner has no session — so the tenant is taken from the `orgid` **query parameter** and the payload's authenticity is whatever the vendor's own signing provides.

Treat the body as untrusted input. `serviceId` is optional and identifies which configured connection the callback belongs to.

#### Signature

```http
POST /connect/webhook/{vendor}/{serviceId} (vendor: string, serviceId: string, orgid?: string, body) -> The vendor-appropriate acknowledgement
```

#### Access

Public — no credentials required.

#### Notes

- Unauthenticated; tenant comes from the query string.

#### Errors

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

#### See also

- `GET /connect/webhook/{vendor}/{serviceId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | query | string | yes | The tenant — this route does not use the `orgid` header. |
| `vendor` | path | string | yes | Partner name. |
| `serviceId` | path | string | yes | Which configured connection. Optional. |
| `orgid` | header | string | — | Organization ID |

### Request body

The vendor's payload, passed through as sent.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The vendor-appropriate acknowledgement |
| `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. |

## GET /connect/oauth2callback/{vendor}

**OAuth callback**

`operationId: ConnectController_oAuthCallback`

The redirect target for an OAuth authorization flow. The browser arrives here with `code` and `state`; the server exchanges the code for tokens and stores them against the integration.

`state` is what ties the callback back to the flow that started it — a callback with a mismatched state is not the one that was initiated.

#### Signature

```http
GET /connect/oauth2callback/{vendor} (vendor: string, code?: string, state?: string) -> A redirect back into the application
```

#### Access

Public — no credentials required.

#### Notes

- Browser-facing redirect target.

#### Errors

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

#### See also

- `POST /upstream/save-integration`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization ID |
| `vendor` | path | string | yes | Partner name. |
| `serviceId` | path | string | yes |  |
| `state` | query | string | yes | Opaque state tying the callback to the initiating flow. |
| `code` | query | string | yes | Authorization code from the provider. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | A redirect back into the application |
| `302` | Redirect to another URL |
| `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. |

## GET /connect/automation/{id}/{stepId}/{entity}/{activity}

**Automation webhook (GET)**

`operationId: ConnectController_handleUnifiedAutomationWebhookGet`

The GET form, for use as a link in an email — a recipient clicking it advances the automation and is then sent to `redirect`. Same unauthenticated, URL-as-credential caveat as the POST form.

#### Signature

```http
GET /connect/automation/{id}/{stepId}/{entity}/{activity} (id: string, stepId: string, entity: string, activity: string, orgId?: string, automationId?: string, redirect?: string) -> A result, or a redirect
```

#### Access

Public — no credentials required.

#### Notes

- Unauthenticated — the URL is the credential.

#### Errors

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

#### See also

- `POST /connect/automation/{id}/{stepId}/{entity}/{activity}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes |  |
| `orgId` | query | string | yes |  |
| `entity` | path | string | yes | What the event concerns. |
| `activity` | path | string | yes | What happened. |
| `id` | path | string | yes | Automation id. |
| `stepId` | query | string | — | Step ID |
| `automationId` | query | string | — |  |
| `redirect` | query | string | — |  |
| `stepId` | path | string | yes | Step to resume at. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | A result, or a redirect |
| `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 /connect/automation/{id}/{stepId}/{entity}/{activity}

**Automation webhook (POST)**

`operationId: ConnectController_handleUnifiedAutomationWebhook`

The unified inbound hook that lets an external event advance an automation — `id` and `stepId` name where in the automation to resume, `entity` and `activity` say what happened.

**Unauthenticated**, with the tenant in the `orgId` query parameter. Anyone who knows the URL can trigger the step, so treat these URLs as capability tokens and do not publish them. `redirect` sends the caller onward afterwards, which is how this is used from an email link.

#### Signature

```http
POST /connect/automation/{id}/{stepId}/{entity}/{activity} (id: string, stepId: string, entity: string, activity: string, orgId?: string, automationId?: string, redirect?: string, body) -> A result, or a redirect
```

#### Access

Public — no credentials required.

#### Notes

- Unauthenticated — the URL is the credential.

#### Errors

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

#### See also

- `GET /connect/automation/{id}/{stepId}/{entity}/{activity}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes |  |
| `orgId` | query | string | yes | The tenant. |
| `entity` | path | string | yes | What the event concerns. |
| `activity` | path | string | yes | What happened. |
| `stepId` | query | string | — | Step ID |
| `id` | path | string | yes | Automation id. |
| `automationId` | query | string | — |  |
| `redirect` | query | string | — | Where to send the caller afterwards. |
| `stepId` | path | string | yes | Step to resume at. |

### Request body

Event payload.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | A result, or a redirect |
| `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. |

