Rest: Pivot's Public API

Overview

The Pivot REST API is public and not used by our client apps. It's purpose is direct integration by customers as well as our own use for building Zapier and Power Automate connectors.

The Rest service is responsible for authentication but not authorization. Rest API requests require a Bearer token passed via the Authorization header of each request. This token is an APIKey which is stored in the database and corresponds to a specific Integration.

Once a Rest route has 1) authenticated the API key as corresponding to an active Integration in the Rest service's own database and 2) determined that the schema of the request body is valid, it uses downstream services for data fetching and mutation.

Rest is written in Go. It's a fairly simple HTPP web server, delegating the complexity of data fetching and mutation to the underlying services it calls with gRPC.

API

Authentication

Note that the current implementation of Integrations is specifically for API Keys and Zapier. It isn't intended (yet) to support third-party apps or OAuth scopes. In the future, those capabilities will possibly be added separately from Rest.

Integration Users and API Keys

The Rest service has an entity Integration and the Facebox service has an entity User. They share the same id. When an application user wants to create a new integration, both the Facebox service and the Rest service are involved. When an application user wants to disable an integration, both the Facebox service and Rest service must update their respective entities. The reason for this coupling is to allow the Rest service to own the concepts of API keys and integrations while allowing Facebox to own the underlying user that every integration corresponds to.

API keys are very specific to the Rest service - they aren't used by other services. An API key used in the Authorization header corresponds to an Integration record in the database which has a 1:1 relationship with a User entity in the Facebox service.

An 'Integration' created by an organization admin in Pivot is really just a user as far as Facebox, Messenger, and Blockhead are concerned, so permissions for integrations are the same as permissions for users. Downstream data services like Messenger and Blockhead basically don't know what Integration are, the services simply run their normal authorization checks to see if the userId provided by the Rest service has the necessary access for the operation. Integrations are therefore authorized just like any other user -- they can be given Organization Admin roles, room memberships, space memberships, etc.

The Visa service crucially does not allow generation of JWTs for users if integration_id has a value according to the Facebox service, so they can't be 'logged-in to' and can't be used to authenticate with the Friend service.

/v1 HTTP Routes

The base url is api.pivot.app/v1 and all requests must include an Authorization header with value bearer [apiKey].

/users

  • Get user GET /users/:id

/spaces

  • Get all spaces GET /spaces
  • Get a space GET /spaces/:id
  • Create a space POST /spaces
  • Update a space PATCH /spaces/:id

/members

  • Get all members for a space GET /spaces/:id/members
  • Get a space member GET /spaces/:id/members/:id
  • Create a space member POST /spaces/:id/members

    Must already know the user id. If you know the email but not the user id, create an invite instead.

  • Update a space member PATCH /spaces/:id/members/:id

/invites

  • Get all invites GET /spaces/:id/invites
  • Get existing invite GET /spaces/:id/invites/:id
  • Update existing invite PATCH /spaces/:id/invites/:id
  • Create invite POST /spaces/:id/invites

/blocks

The Block entity is used generically for all GET operations, however different block types have their own POST and PATCH operations which return blocks.

  • GET /blocks/:id
  • GET /blocks?spaceId?=:id&parentId=:id
    • Either spaceId or parentId is required and the other must be undefined. This operation will not return all blocks the user has access to, only those for a given spaceId (with no parent) or a given parent blockId.
/database-items
  • POST /blocks/database-items
  • PATCH /blocks/database-items/:id
/page
  • POST /blocks/pages

Entities

  • User
  • Invite
  • Space Member
  • Space
  • Block

NATS

// TODO: Clarify if webhooks are part of Rest and if so, leverage NATS.

Database

Rest uses Amazon Keyspaces (managed Cassandra) for its data storage needs.

  1. Integration - an integration is an identity that the Rest service can be accessed via. It corresponds to a user_id in Facebox, which Rest can then pass to downstream services, so that those services an run their normal Authz checks on RPCs from Rest.

Deployment

Temporal Workflows

N/A

Security