References

Outpost API Reference

The API is a REST-based JSON API that can be publicly exposed or only available on your internal network / VPC, depending on your network topology.

Authentication

Admin API Key

The API uses bearer token authentication with a token of your choice configured through the API_KEY environment variable.

JWT Token

The API can also be authenticated using a per tenant token that’s valid for 24 hours. When using the a JWT token the /:tenant_id of each API endpoints is inferred to be the authenticated token and is not necessary.

Tenants

The API segments resources per tenant. A tenant represents a user/team/organization in your product. The provided value determines the tenant's ID, which can be any string representation.

If your system is not multi-tenant, create a single tenant with a hard-code tenant ID upon initialization. If your system has a single tenant but multiple environments, create a tenant per environment, like live and test.

Tenant Object

{
  "id": "123", //User-defined system ID
  "destinations_count": 5, // Integer
  "topics": ["user.created", "user.deleted"], // List of subscribed topics across all destinations
  "created_at": "2024-01-01T00:00:00Z" // ISO Date
}
json

PUT /:tenant_id

Idempotently creates the tenant. A tenant is required to associate a destination.

Request

Empty body

Response

{
  "id": "123",
  "destinations_count": 5,
  "topics": ["user.created", "user.deleted"],
  "created_at": "2024-01-01T00:00:00Z"
}
json

GET /:tenant_id

Get a tenant.

Response

{
  "id": "123",
  "destinations_count": 5,
  "topics": ["user.created", "user.deleted"],
  "created_at": "2024-01-01T00:00:00Z"
}
json

GET /:tenant_id/portal

Return a redirect URL for a user portal URL. The redirect URL contains a JWT that authenticates the user with the portal.

Request

Supported parameters:

  • ?theme=(light|dark) Optional query param to force a specific theme to display the portal in to match the current theme of your own dashboard

Response

{
  "redirect_url": "https://webhooks.acme.com?token=JWT_TOKEN" // Redirect URL with authentication token
}
json

GET /:tenant_id/token

Return a JTW token to authenticate the user with the API scoped to their specific tenant in order to call the API from the browser safely.

Response

{
  "token": "SOME_JWT_TOKEN"
}
json

DELETE /:tenant_id

Delete the tenant and all associated destinations

Request

Empty body

Response

{
  "success": true
}
json

Destinations

Destination Object

{
  "id": "des_12345", // Control plane generated ID or user provided ID
  "type": "webhooks", // Type of the destination
  "topics": ["user.created", "user.updated"], // Topics of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks/user"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "signing_secret": "some***********"
  },
  "disabled_at": null, // null or ISO date if disabled
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}
json

The topics array can contain either a list of topics or a wildcard * implying that all topics are supported. If you do not wish to implement topics for your application, you set all destination topics to *.

By default all destination credentials are obfuscated and the values cannot be read. This does not apply to the webhook type destination secret and each destination can expose their own obfuscation logic.

GET /:tenant_id/destinations

Return a list of the destinations. The endpoint is not paged, and the maximum number is equivalent to the maximum configured number of destinations per tenant through the MAX_DESTINATIONS_PER_TENANT env variable.

Request

Supported Parameters:

  • type string | string[] The type of destinations to return
  • topics string | string[] Return destinations for a specific event type

Response

[{
  "id": "dest_123456", // Control plane generated ID or user provided ID
  "type": "webhooks", // Type of the destination
  "topics": ["user.created", "user.updated"], // Type of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks/user"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "secret": "something-super-secret"
  },
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}]
json

POST /:tenant_id/destinations

Create a new destination type with the provided configuration.

Request

{
  "id": "123", // Optional, UUID will be generated if empty
  "type": "webhooks", // String of valid destination type
  "topics": "*", // '*' or String[] of enabled topics, "*" for all
  "config": { // Config object for the given type
    "url": "https://example.com/webhooks"
  },
  "credentials": null // Credentials for the given type. It can be empty or null.
}
json

Response

{
  "id": "des_12345", // ID of the destination
  "type": "webhooks", // Type of the destination
  "topics": ["*"], // Topics of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "signing_secret": "some************"
  },
  "disabled_at": null, // null or ISO date if disabled
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}
json

Webhook secret & rotation

Webhook secrets and rotations are a special case for the webhook destination type. The destination type credentials.secret is only a valid input when using the Admin API and can be omited when omited a secret is generated automatically.

Additionally, credentials.previous_secret can be used to set a rotated secret during a migration. credentials.rotate_secret can be used to automatically rotate the existing secret which results in a new credentials.secret and credentials.previous_secret value.

previous_secret are valid and used to “double” sign the request for 24 hours.

PATCH /:tenant_id/destinations/:destination_id

Update the destination configuration.

Request

{
  "type": "webhooks", // Optional. String of valid destination type
  "topics": "*", // Optional. String[] of enabled topics, "*" for all
  "config": { // Optional. Config object for the given type
    "url": "https://example.com/webhooks"
  },
  "credentials": null // Optional. Credentials for the given type. It can be empty or null.
}
json

Response

{
  "id": "des_12345", // Control plane generated ID
  "type": "webhooks", // Type of the destination
  "topics": "*", // Topics of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "signing_secret": "some********"
  },
  "disabled_at": null, // null or ISO date if disabled
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}
json

If the destination uses OAuth:

{
  "redirect_url": "https://dashboard.hookdeck.com/authorize?token=12313123"
}
json

PUT /:tenant_id/destinations/:destination_id/enable

Enable a previously disabled destination.

Request

Empty body

Response

{
  "id": "des_12345", // Control plane generated ID
  "type": "webhooks", // Type of the destination
  "topics": "*", // Topics of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "signing_secret": "some************"
  },
  "disabled_at": null, // null or ISO date if disabled
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}
json

PUT /:tenant_id/destinations/:destination_id/disable

Disable a previously enabled destination.

Request

Empty body

Response

{
  "id": "des_12345", // Control plane generated ID
  "type": "webhooks", // Type of the destination
  "topics": "*", // Topics of events this destination is eligible for
  "config": { // Destination type specific configuration. Schema of depends on type
    "url": "https://example.com/webhooks"
  },
  "credentials": { // Destination type specific credentials. AES encrypted. Schema depends on type
    "signing_secret": "some***********"
  },
  "disabled_at": "2024-01-01T00:00:00Z", // null or ISO date if disabled
  "created_at": "2024-01-01T00:00:00Z" // Date the destination was created
}
json

DELETE /:tenant_id/destinations/:destination_id

Delete the destination.

Request

Empty body

Response

{
  "success": true
}
json

Publish

Publish events on one or more topics.

POST /api/v1/publish

Publish an event.

Request

{
  "tenant_id": "<TENANT_ID>",
  "topic": "topic.name", // Topic defined in TOPICS environment variable
  "eligible_for_retry": true | false, // Should event delivery be retried
  "metadata": Payload, // can by any JSON payload,
  "data": Payload // can by any JSON payload
}
json

Response

Empty body

Example

curl --location 'localhost:3333/api/v1/publish' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_KEY>' \
--data '{
    "tenant_id": "<TENANT_ID>",
    "topic": "user.created",
    "eligible_for_retry": true,
    "metadata": {
        "meta": "data"
    },
    "data": {
        "user_id": "userid"
    }
}'
sh

Schemas

GET /destination-types

Runs a list of JSON-based input schemas for each destination type.

Request

No parameters.

Response

[
  {
    "type": "webhook",
    "label": "Webhook",
    "description": "Send event via an HTTP POST request to a URL of your choice",
    "icon": "<svg />",
    "instructions": "Some *markdown*",
    "config_fields": [
      {
        "type": "text",
        "label": "URL",
        "description": "The URL to send the event to",
        "validation": "/((([A-Za-z]{3,9}:(?://)?)(?:[-;:&=+$,w]+@)?[A-Za-z0-9.-]+(:[0-9]+)?|(?:www.|[-;:&=+$,w]+@)[A-Za-z0-9.-]+)((?:/[+~%/.w-_]*)???(?:[-+=&;%@.w_]*)#?(?:[w]*))?)/",
        "required": true
      }
    ],
    "credential_fields": []
  },
  {
    "type": "hookdeck",
    "label": "Hookdeck Event Gateway",
    "description": "Send event to Hookdeck Event Gateway",
    "icon": "<svg />",
    "instructions": "Some *markdown*",
    "remote_setup_url": "https://dashboard.hookdeck.com/authorize?provider=acme",
    "config_fields": [],
    "credential_fields": [
      {
        "type": "text",
        "label": "Publishing Key",
        "description": "Your Hookdeck source publishing key",
        "required": true
      }
    ]
  }
]
json

GET /destination-types/:type

Runs the input schemas for the specified destination type.

Response

{
  "type": "webhook",
  "label": "Webhook",
  "description": "Send event via an HTTP POST request to a URL of your choice",
  "icon": "<svg />",
  "instructions": "Some *markdown*",
  "config_fields": [
    {
      "type": "text",
      "label": "URL",
      "description": "The URL to send the event to",
      "validation": "/((([A-Za-z]{3,9}:(?://)?)(?:[-;:&=+$,w]+@)?[A-Za-z0-9.-]+(:[0-9]+)?|(?:www.|[-;:&=+$,w]+@)[A-Za-z0-9.-]+)((?:/[+~%/.w-_]*)???(?:[-+=&;%@.w_]*)#?(?:[w]*))?)/",
      "required": true
    }
  ],
  "credential_fields": []
}
json

Events API

GET /:tenant_id/destination/:destination_id/events

Retrieve a list of events using a cursor navigation.

Supported parameters

  • destination_id string | string[] Return events for a specific destination
  • status success | failed Return events with a specific failed or success status

Response

[{
  "id": "123",
  "destination_id": "456",
  "topic": "something.created",
  "time": "2024-01-01T00:00:00Z",
  "succesful_at": "2024-01-01T00:00:00Z" 
  "metadata": {
    "key": "value" // String, number or boolean
  },
  "data": { // Freeform JSON data
    "hello": "world"
  }
}]
json

GET /:tenant_id/destination/:destination_id/events/:event_id

Retrieve a specific event and its associated data.

Response

[{
  "id": "123",
  "destination_id": "456",
  "topic": "something.created",
  "time": "2024-01-01T00:00:00Z",
  "succesful_at": "2024-01-01T00:00:00Z" 
  "metadata": {
    "key": "value" // String, number or boolean
  },
  "data": { // Freeform JSON data
    "hello": "world"
  }
}]
json

GET /:tenant_id/destination/:destination_id/events/:event_id/deliveries

Retrieve a list of the delivery attempts with the associated responses.

Response

[{
  "delivered_at": "2024-01-01T00:00:00Z",
  "status": "success",
  "code": "200", // "OK", "ERR" or a valid HTTP status code
  "response_data": {
    "hello": "world"
  }
}]
json

POST /:tenant_id/destination/:destination_id/events/:event_id/retry

Submit an event for retry

Response

{ "success": true }
json