Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cmd/tools/genprovider/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ type UIMetadata struct {
Label string `json:"label"`
Description string `json:"description"`
Icon string `json:"icon"`
RemoteSetupURL string `json:"remote_setup_url,omitempty"`
SetupLink *struct {
Href string `json:"href"`
Cta string `json:"cta"`
} `json:"setup_link,omitempty"`
}

type FieldSchema struct {
Expand Down
23 changes: 17 additions & 6 deletions docs/apis/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1987,15 +1987,26 @@ components:
type: string
description: Markdown instructions.
example: "Some *markdown*"
remote_setup_url:
type: string
format: url
setup_link:
type: object
# Property is optional, not nullable
description: >-
Some destinations may have Oauth flow or other managed-setup flow that can be triggered with a link. If a `remote_setup_url` is set then the user should be prompted to follow the link to configure the destination.
Some destinations may have an OAuth flow or other managed-setup flow that can be triggered with a link. If a `setup_link` is set then the user should be prompted to follow the link to configure the destination.

See the [building your own UI guide](https://outpost.hookdeck.com/guides/building-your-own-ui.mdx) for recommended UI patterns and wireframes for implementation in your own app.
example: "https://dashboard.hookdeck.com/authorize?provider=acme"
properties:
href:
type: string
format: url
description: The URL to direct the user to for setup.
example: "https://dashboard.hookdeck.com/connect"
cta:
type: string
description: The call-to-action button text to display to the user.
example: "Generate Hookdeck Token"
required:
- href
- cta
config_fields:
type: array
description: Config fields are non-secret values that can be stored and displayed to the user in plain text.
Expand Down Expand Up @@ -4078,7 +4089,7 @@ paths:
description: "Send event via an HTTP POST request to a URL"
icon: "<svg />"
instructions: "Enter the URL..."
# remote_setup_url is optional, omitted here
# setup_link is optional, omitted here
config_fields: [
{
key: "url",
Expand Down
12 changes: 6 additions & 6 deletions docs/content/guides/building-your-own-ui.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Each entry typically includes (confirm names and optionality in OpenAPI):
- `label`, `description`, `icon` — Display metadata; `icon` is often an SVG string (some older code used the name `svg`). Sanitize if you render inline HTML.
- `config_fields`, `credential_fields` — Field definitions for the config step (snake_case in JSON). Include every field from both arrays on create and edit.
- `instructions` — Markdown for complex setup (for example cloud resources).
- `remote_setup_url` — Optional external setup flow before or instead of inline fields.
- `setup_link` — Optional object (`href` + `cta`) for an external setup flow before or instead of inline fields.

### Dynamic field shape (for forms)

Expand All @@ -125,17 +125,17 @@ Field objects are fully described in OpenAPI (`DestinationSchemaField`), includi

This section matters whether you use an **official SDK** on the server (recommended when available) or raw HTTP: the **HTTP API** always follows [OpenAPI](/docs/outpost/api), while SDKs present language-native types to your backend code.

HTTP responses from Outpost on the wire use JSON property names that match OpenAPI—typically **snake_case** (for example `config_fields`, `credential_fields`, and `remote_setup_url` on `GET /destination-types`).
HTTP responses from Outpost on the wire use JSON property names that match OpenAPI—typically **snake_case** (for example `config_fields`, `credential_fields`, and `setup_link` on `GET /destination-types`).

Official **SDKs** deserialize into language-native structures; names often differ from the wire format (for example TypeScript may expose **camelCase** such as `configFields` and `credentialFields`). Mutations use each SDK’s documented request types, which may not mirror OpenAPI field names literally.

When a **browser** loads destination-type metadata via **your** backend, it receives whatever JSON your server returns. Options include forwarding the **raw** Outpost response body (so the client matches OpenAPI) or translating once on the server and treating that as your product’s contract. In all cases, create and update bodies must still place each value under the schema field’s **`key`** inside `config` and `credentials` as defined in OpenAPI.

**Shape mismatches** between layers often appear as missing dynamic fields or create errors referencing absent `config.*` keys (for example `config.url` for webhooks). Comparing the **actual** JSON your UI receives with the property names your rendering code expects (`config_fields` versus `configFields`, and similar) usually isolates the problem.

### Remote setup URL
### Setup link

When `remote_setup_url` is present, you can link users through an external setup flow (for example Hookdeck-managed configuration) instead of only inline fields.
When `setup_link` is present, you can link users through an external setup flow (for example Hookdeck-managed configuration) instead of only inline fields. The object contains `href` (the URL) and `cta` (button text to display).

### Instructions

Expand Down Expand Up @@ -172,7 +172,7 @@ The product flow is three steps; the API is typically one [create destination](/
### Step 3 — Configure the destination

- Read `config_fields` and `credential_fields` for the selected type from `GET /destination-types` (or a single-type endpoint if you use one—see OpenAPI).
- If `remote_setup_url` is set, consider that flow first.
- If `setup_link` is set, consider that flow first.
- Otherwise render fields per [Dynamic field shape](#dynamic-field-shape-for-forms) and submit via [Create destination](/docs/outpost/api/destinations#create-destination).

**Reference:** [DestinationConfigFields.tsx](https://github.com/hookdeck/outpost/blob/main/internal/portal/src/common/DestinationConfigFields/DestinationConfigFields.tsx)
Expand Down Expand Up @@ -220,7 +220,7 @@ For **customer-facing** destination and delivery UI, work through **Planning and

- [ ] List view shows type, human-readable target, and subscribed topics; each row reaches detail edit and destination-scoped activity.
- [ ] Create flow covers: pick type → select topics (`GET /topics`) → collect `config` and credentials per the selected type’s `config_fields` and `credential_fields`.
- [ ] When a type exposes `instructions` or `remote_setup_url`, the UI surfaces them (markdown / external flow) so customers are not blocked on opaque fields.
- [ ] When a type exposes `instructions` or `setup_link`, the UI surfaces them (markdown / external flow) so customers are not blocked on opaque fields.
- [ ] Detail supports lifecycle your product needs: view, update, delete, enable/disable—per OpenAPI and your product policy.

### Activity, attempts, and retries
Expand Down
Loading