Skip to content
Helix Docs

Connect an API that isn't listed

Connect an API that isn't in the supported services list with a generic service, from bearer token and API key to OAuth 1.0a, HMAC, and AWS Signature v4.

For developers Updated Oct 2, 2026
View as Markdown

If the API you need isn’t in the supported services list, connect it with one of six generic services: HTTP Bearer Token, HTTP Basic Authentication, Custom Token Authentication, HTTP OAuth 1.0a, HTTP HMAC signature, or HTTP AWS Signature v4. You enter the credential once in the dashboard, and your function calls the API with ctx.http.authed('alias') like any other connected service. The platform adds the credential to the request, so the secret never reaches your code.

This page walks through the whole path with a made-up credential against a public test API, so you can run it without a third-party account.

Pick a generic service

If the API expectsPick
Authorization: Bearer <token>HTTP Bearer Token
A username and password, or an API token used as the passwordHTTP Basic Authentication
A token or API key in a header you name, or in the query stringCustom Token Authentication
An OAuth 1.0a signed requestHTTP OAuth 1.0a
A signature computed over the request, such as X-Signature: ...HTTP HMAC signature
An AWS Signature v4 signed requestHTTP AWS Signature v4

OAuth 2.0 with token refresh is not a generic service. If the service offers OAuth 2.0, use its own entry in the supported services list, which handles sign-in and refresh for you.

What to enter in the form

ServiceFields
HTTP Bearer TokenToken
HTTP Basic AuthenticationUsername, Password
Custom Token AuthenticationToken, Location, Location Value, Pin to domain (optional)
HTTP OAuth 1.0a, HTTP HMAC signature, HTTP AWS Signature v4Described in signed requests below

For Custom Token Authentication:

FieldValue
TokenThe API key or token
Locationheader (the default) or query for the query string
Location ValueThe header name, such as X-Api-Key, or the query parameter name, such as api_key
Pin to domainOptional, and recommended. The only domain this credential may be used with, such as api.vendor.com. Subdomains are included. Enter the bare domain: no https://, path, wildcard, or port

Signed requests

OAuth 1.0a, HMAC, and AWS Signature v4 sign each request instead of sending a fixed token. You enter the secrets once, and the platform computes the signature on every call.

Pin to domain is required

A signed credential can only be used against the domain you pin it to, and its subdomains. api.vendor.com allows eu.api.vendor.com, not vendor.com. A request to any other host fails instead of sending the credential. Enter the bare domain: no https://, path, wildcard, or port.

These services also refuse to send a request when a required value is missing.

HTTP OAuth 1.0a

FieldValue
Consumer keyThe key issued to your application
Consumer secretThe secret issued to your application
TokenOptional. Leave Token and Token secret empty for two-legged OAuth
Token secretOptional, as above
Signature methodHMAC-SHA1 (the default) or HMAC-SHA256
Pin to domainRequired

You supply the credentials. Helix signs each request with them but doesn’t run the OAuth 1.0a token exchange, so for an API that needs a user’s access token you must already hold the token and token secret.

Not supported:

  • The realm parameter
  • The RSA-SHA1 and PLAINTEXT signature methods
  • Requests with a form-urlencoded body

HTTP HMAC signature

FieldValue
SecretThe shared secret the API verifies against
Algorithmsha1, sha256 (the default), or sha512
Signature encodinghex (the default) or base64
Header nameThe header that carries the signature, such as X-Signature
Signature formatThe header value, which must contain {{signature}}, such as sha256={{signature}}
Sign the request bodytrue (the default) or false
Signed headersOptional, comma-separated, in order. Your function sets these headers on the request
Pin to domainRequired

The signature covers the exact bytes your function sends. If the API verifies a re-serialized version of the body, the signatures won’t match. Sign the body, or list at least one signed header.

HTTP AWS Signature v4

FieldValue
Access keyThe AWS access key ID
Secret keyThe AWS secret access key
Session tokenOptional, for temporary credentials
Signing service nameOptional. Only needed when the host doesn’t name the service
RegionOptional. Only needed when the host doesn’t name the region
Pin to domainRequired, and prefilled with amazonaws.com

The region and service come from a regional host such as sts.us-east-1.amazonaws.com. Set them yourself when the host doesn’t name them, or names a different service than the one that signs. For example, bedrock-runtime signs as bedrock.

Worked example

This example uses httpbin.org, a public API that echoes back what it receives. The token below is made up. Don’t enter a real secret while you try this.

1. Create the authentication

helix auth connect --new

The command opens the dashboard’s connect page for your workspace. Add --no-open to print the link instead. In the dashboard, choose HTTP Bearer Token, enter demo-token-123 as the token, and name the authentication.

Back in the terminal, the CLI finds the new authentication and writes an alias into helix.config.ts. The CLI suggests an alias from the service name, so here it is http_bearer_token. You can type a different one at the prompt, using lowercase letters, digits, and underscores, starting with a letter. Without a terminal, such as in an agent loop, the command only prints the link. Once you’ve created the authentication, wire it up with helix auth connect or helix auth add <alias> <uuid>.

2. Call the API

// functions/api/v1/demo.get.ts
import { defineFunction } from '@trayai/helix-sdk';

export default defineFunction(async (ctx) => {
  const res = await ctx.http
    .authed('http_bearer_token')
    .get('https://httpbin.org/bearer');

  return res.body;
});

An authed call returns { status, body, headers }. body is already parsed JSON for a JSON response. A non-2xx answer from the API is returned, not thrown, so check res.status when you need to handle errors.

3. Run it

helix dev
curl http://localhost:3000/api/v1/demo

Success looks like this:

{ "authenticated": true, "token": "demo-token-123" }

The test API received Authorization: Bearer demo-token-123, which your function never wrote.

Try the other two

The same steps work with the other generic services. Change the alias and the URL in step 2, and return res.body as before.

ServiceEntered in the formCallResponse shows
HTTP Basic AuthenticationUsername tester, password s3cret-passhttps://httpbin.org/basic-auth/tester/s3cret-pass{"authenticated": true, "user": "tester"}
Custom Token AuthenticationLocation query, Location Value api_keyhttps://httpbin.org/anythingargs contains api_key with your token
Custom Token AuthenticationLocation header, Location Value X-Api-Keyhttps://httpbin.org/headersThe X-Api-Key header with your token

Try the signed services

Each example uses a public test API and made-up or published test keys, so you need no real account. Create the authentication as in step 1 above. The aliases below are the CLI’s suggested defaults (http_oauth1, http_hmac, http_aws_sigv4), and you can edit them at the prompt. Call each from a function that returns the result:

// functions/api/v1/signed.get.ts
import { defineFunction } from '@trayai/helix-sdk';

export default defineFunction(async (ctx) => {
  const res = await ctx.http.authed('http_oauth1').get('https://postman-echo.com/oauth1');
  return { status: res.status, body: res.body };
});

OAuth 1.0a

Postman Echo checks the signature with its published test key.

FieldValue
Consumer keyRKCGzna7bv9YD57c
Consumer secretD+EdQ-gs$-%@2Nu7
Token and Token secretLeave empty
Signature methodHMAC-SHA1
Pin to domainpostman-echo.com

Call GET https://postman-echo.com/oauth1. Success is status 200 with this body:

{ "status": "pass", "message": "OAuth-1.0a signature verification was successful" }

HMAC signature

FieldValue
Secretdummy-hmac-secret
Algorithmsha256
Signature encodinghex
Header nameX-Signature
Signature format{{signature}}
Sign the request bodytrue
Signed headersLeave empty
Pin to domainhttpbin.org

Send a JSON body to the echo endpoint:

const res = await ctx.http
  .authed('http_hmac')
  .post('https://httpbin.org/anything', { body: { event: 'order.created', id: 42 } });

The echo shows the exact string sent in body.data and the signature in body.headers['X-Signature']. For this body and secret the signature is eec200cc0004a0c3ceb9aeb1a4ddea237a549f1f65a11c40352347cbfdc394b4. Check it yourself:

printf '%s' '{"event":"order.created","id":42}' | openssl dgst -sha256 -hmac 'dummy-hmac-secret'

AWS Signature v4

FieldValue
Access keyAKIDEXAMPLE
Secret keywJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY
Session tokenLeave empty
Pin to domainamazonaws.com

These are the example keys from AWS’s own documentation, so AWS rejects them. Call GET https://sts.us-east-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15. Success for this exercise is status 403 with <Code>InvalidClientTokenId</Code> in the body. That shows AWS parsed a correctly formed signed request and rejected only the key. An unsigned request returns MissingAuthenticationToken instead. This does not prove the signature is valid, only that it is well formed. With a real key, the same call returns your account details.

Troubleshooting

The API answers 401. The call doesn’t throw: the 401 comes back as res.status === 401. The values or the location are wrong. Check the Token, Location, and Location Value you entered against what the API’s documentation asks for.

You want to see what is sent. Point a made-up credential at an echo endpoint such as https://httpbin.org/anything. Never do this with a real secret, because the echo site would receive it.

A signed request is refused. HTTP OAuth 1.0a, HTTP HMAC signature, and HTTP AWS Signature v4 send nothing when a required value is missing or the host is outside the pinned domain. Check the form values and the Pin to domain against the URL you call.

A missing alias error. The alias isn’t in helix.config.ts. The error lists the aliases that are configured, so compare it with the name your code uses.

For how aliases, refresh, and request logging work, see connected services.

Loading search…

Jump to a section

tab to move · esc to close