Where to look#
- Integration logs (Integrations, Integration logs): every call Subcontext made to your systems, and every delivery your systems sent in. Filter by integration, endpoint, direction (outbound or inbound), result, status and date. Open a call to see the address, your status, how long it took, the error, the Agent tool that made it (if any), and the start of the request and response bodies, with secrets removed.
- The integration's page: its status (credentials rejected or paused), the latest calls, Resume when it's paused, and Test and Logs on each endpoint.
- The workflow: Last few runs on its page, and Activity for every run, with each action's outcome and why it failed.
- Decisions, the tool calls: what the agent sent and what it was told.
- External systems: a count of recent failures on each connection.
"No response" in the logs means the request never got an answer, because of a timeout, a refused connection, or a certificate problem.
Errors and what to do#
Calls from Subcontext to you#
Errors about the address, your server's answer and credentials are in the Integration logs. Errors in the set-up (templates, variables, path parameters, success conditions) stop or fail the call on Subcontext's side, so look for those on the workflow run (Activity) or the agent's tool call (Decisions). Test on the endpoint shows them too.
| What you see | What it means | What to do |
|---|---|---|
integration URLs must use https |
The address starts with http://. |
Serve your endpoint over HTTPS and update the address. |
integration URLs must not target private hosts |
The address is localhost, a private address, a .local or .internal name, or a name that resolves to one. |
Use a public address. To try things on your own computer, use a tunnelling service that gives you a public https:// address. |
integration host ... doesn't resolve |
The hostname isn't in DNS. | Check the spelling, and that the DNS record exists. |
remote returned 502 (or another 5xx), or "No response" |
Your server failed or didn't answer within 15 seconds. | Check your server's logs. Answer faster and do slow work afterwards. Subcontext retries these. |
remote rejected request (404) (or another 4xx) |
Your server refused the request. Not retried. | Open the call to see the request and your answer. Common causes: the path or base URL is wrong, the body template doesn't produce what your API expects, or a redirect (a 3xx is a refusal too). |
authentication rejected (401), or the connection shows credentials rejected |
Your server didn't accept the credential. | Check the secret variable the auth settings use, then Rotate Secret (custom integrations) or save new credentials on the connection's Configure page. Either brings the connection back, and so does a Test that passes. |
remote rejected request (401) on a webhook |
Your receiver refused that delivery, usually because the signature didn't check out. | Check the receiver uses the raw body and the right secret (see below). Later deliveries still go out. |
client credentials rejected |
Your token URL refused the client id or secret. | Check both variables and the Token URL, and whether it wants them in the form body or a Basic header (Send the client id and secret on the integration). |
token endpoint returned no access_token |
Your token URL answered, but without access_token in its JSON. |
Return {"access_token": "...", "expires_in": 3600}. |
success conditions failed for <endpoint> |
Your server answered 2xx, but the answer didn't pass the endpoint's Success conditions. |
Compare the answer in the log with the conditions. |
rendered request body for <endpoint> is not valid JSON |
The body template made something that isn't JSON. | Put `\ |
rendered form body ... must be a flat JSON object |
A form-encoded endpoint's template made nested objects or lists. | Make the template produce one flat object. |
missing path parameter <name> |
The path has {{name}} but nothing filled it. |
Give the tool a parameter of that name, or (for workflows) use a variable the workflow has. |
auth is not configured / unknown variable secret.<name> |
The auth settings or a header point at a variable that doesn't exist. | Create the variable, or choose an existing one. |
| The connection shows paused | 10 temporary failures in a row, so Subcontext stopped calling it and told your owners and managers. | Fix your side. Subcontext tries one send every 15 minutes and carries on once one gets through, or press Resume to start straight away. See Too many failures in a row. |
What an agent says#
| The agent is told | Look at |
|---|---|
the API rejected the request (status ...) |
Your answer, which the agent sees in part. Make the message a plain sentence the agent can act on. |
the external system is temporarily unavailable |
Your server's health, response time, or the connection's status. |
this integration is misconfigured or unavailable |
The credentials (a 401) and the integration's set-up. The log shows the real error. |
this integration is not connected yet |
The custom integration has no working connection. Email hello@subcontext.com. |
missing required parameter(s): ... |
The tool's Description: tell the agent to ask the customer for it first. |
Action requires human approval |
Someone in your firm needs to approve the call. |
Deliveries from your systems to Subcontext#
| Status | Cause | What to do |
|---|---|---|
403 with "no webhook signing secret configured" in the log |
The inbound integration has no Signing secret variable. | Create a secret variable and choose it on the integration. |
403 "malformed signature header" |
The header is missing, has the wrong name, or isn't t=...,v1=.... |
Check the Signature header name on the integration matches what you send. |
403 "stale webhook timestamp" |
t is more than 5 minutes from Subcontext's clock. |
Sync your server's clock, and sign each attempt when you send it, not when you queue it. |
403 "signature mismatch" |
The secret is different, or the body changed after signing. | Sign the exact string you send. Don't let a library re-encode the JSON after you sign it. |
400 |
The body isn't valid JSON. | Send Content-Type: application/json and one JSON object. |
404 |
Wrong address, or the integration was revoked. | Copy the Delivery URL again. |
200, but nothing was recorded |
The event's type isn't in your Outcome event types or Update event types, the type isn't at the Event type path, or the outcome couldn't be matched to a lead. | Check the paths in the integration's settings against a real event in the log. Unmatched outcomes wait in Outcomes to match. |
Webhooks you receive#
- Every signature fails. Check you're using the raw body. Frameworks that
parse JSON for you usually have a way to get the raw bytes (
express.raw()in Express,request.get_data()in Flask,php://inputin PHP). Check the secret matches the connection's Signing secret exactly, with no spaces. - No signature header at all. The connection was set up before signing secrets were required and still has none (it's marked unsigned). Open its Configure page and press Generate.
- The same event twice. This happens after a timeout or a retry. Skip repeated
Idempotency-Keyvalues. - Sends stopped. Check the connection's status. Paused means 10
temporary failures in a row. Subcontext tries again every 15 minutes, or you
can press Resume. A
401from your receiver refuses only that delivery. - A workflow ran but nothing was sent. Open the run from Activity: a paused campaign, a switched-off workflow or action, or a connection that isn't active all stop the send, and the run says which.
Still stuck?#
Email hello@subcontext.com with the integration's name and the time of a failed call. Never send a secret or signing secret.