Skip to main content
An API connector lets the workspace’s AI call your REST API. When the person asking is one of your embedded users, the call must be made as them, never as someone else. You choose how Upsolve does that when you add the connector (Connections → API). Keep one API key on the connector. It is stored encrypted and only ever sent to your API’s base URL. A binding tells Upsolve which parameter names the user, and which property supplies its value: The properties are the ones you pass to POST /v1/api/projects/embed-token in organization.properties and user.properties, the same ones row-level security reads. If your API wants the account id in a header, send it once at sign-in and bind it:
embed-token (excerpt)
Binding
How it behaves:
  • The model never chooses the user. A bound parameter is removed from the tool’s schema and set by Upsolve on every call. If the model supplies one anyway, it is dropped.
  • Properties are read on the server, not from the token in the browser, so a user cannot change them.
  • It fails closed. A user who has no value for a bound property gets none of the connector’s tools, with the reason shown (“Your account has no account_id.”).
  • Operations that do not take every bound parameter are hidden, unless you mark them global (a plan list, a lookup table). A server key can act for any account, so a call without its binding could read across customers.
  • The property must be a string, number or boolean. An empty or missing value counts as missing.
Upsolve enforces the binding; your API does not see who is asking. It is the same trust as giving Upsolve database credentials with row-level security: the key can act for any account, and Upsolve only ever sends the caller’s own.

OAuth

Enter your OAuth client ID and secret, the authorization and token endpoints (prefilled from your OpenAPI spec when it declares them) and the scopes. Each user signs in once in a popup. Upsolve stores their tokens encrypted and refreshes them, so rules and scheduled work keep running. If a refresh is refused, the user sees “needs to be reconnected” and their rules pause until they connect again. The client secret is only sent to your token endpoint.

Token callback

Use this when your API only accepts tokens issued per user and has no server key. Upsolve asks your endpoint for a token each time it needs one for a user. When you create the connector, Upsolve shows a callback secret (upsk_...) once. Store it on your server. You can rotate it from the connector’s settings, which invalidates the old one at once. Test callback calls your endpoint as you and reports the status, latency and token lifetime. The token itself is never shown.

The request

  • externalUserId and externalOrganizationId are the externalId values you sent to embed-token. They are null for a member of your Upsolve organization who is not one of your embedded users.
  • scopes are the scopes you configured on the connector.
  • The timestamp is Unix seconds. The signature is the lowercase hex HMAC-SHA256 of <timestamp>.<raw body>, keyed with the callback secret.

Your response

accessToken and expiresIn (seconds, up to 7 days) are required. tokenType defaults to Bearer. The token is sent as Authorization: Bearer <token> unless you configured another header and prefix. The answer must be JSON under 64 KB.

What to check on your side

  1. Verify the signature over the raw body before parsing it. Re-serialised JSON will not match.
  2. Reject timestamps more than 300 seconds from your clock.
  3. Compare in constant time.
  4. Look the user up by externalUserId. If you do not know them, or they are not entitled to this API, answer with a 4xx.
  5. Return a short-lived token for that user only.

Failures

Caching

Upsolve keeps each token in memory for its user and connector until 60 seconds before it expires (at most 24 hours), so your endpoint is called roughly once per token lifetime per user. Simultaneous requests for one user share a single call. Tokens are never written to a database or a log, and rotating the secret clears them.

Samples

Both samples are complete, tested endpoints you can copy: examples/api-connector-token-callback has a Node (Express) and a Python (FastAPI) version, with the contract in its README. The verification function in each:
Replace the sample’s mintTokenFor / mint_token_for stub with your own user lookup and token issuer.