Skip to main content
POST https://app.vern.so/api/v1/migrations/{migration_id}/runs/{run_id}/credentials
When a run extracts from a live source whose connector still needs secrets, the managed agent pauses and asks for them. The run reports status: "blocked" with blocked_reason: "credentials", and this endpoint is the only way to answer it.
Never send credentials as a message answer — the messages endpoint rejects a credential-blocked run with 409 for exactly this reason. Secrets sent here go straight to a secured vault and never enter the agent thread, the run row, or logs; the agent resumes with a sanitized confirmation only.
{migration_id} and {run_id} come from starting and polling the run.

Authentication

Requires an x-api-key header. See Authentication.

What you’re answering

A credential-blocked poll response tells you exactly what to collect:
{
  "run_id": "d4c3b2a1-...",
  "status": "blocked",
  "blocked_reason": "credentials",
  "credential_request": {
    "connection_id": "9b1f2c3d-...",
    "source_key": "salesforce",
    "source_name": "Salesforce",
    "reason": "I need API access to read your contacts.",
    "guidance": {
      "summary": "Create a connected app and copy its OAuth credentials.",
      "steps": ["Open Setup → App Manager", "New Connected App", "Copy the consumer key and secret"],
      "links": [{ "label": "Salesforce docs", "url": "https://help.salesforce.com/…" }]
    },
    "schema": { "client_id": { "type": "string" }, "client_secret": { "type": "string", "secret": true } }
  }
}
Render a form from credential_request.schema, show the guidance, and post the collected values back.

Request body

credentials
object
required
The secret values, keyed to match the request’s schema (e.g. { "client_id": "…", "client_secret": "…" }). Must be a non-empty object.
connection_id
string
Optional guard. If sent, it must match the credential_request.connection_id the run asked about, or the call returns 409. The connection is always taken from the run itself — a key can only ever fill the connection the agent actually requested.

Response

200 OK
{
  "run_id": "d4c3b2a1-9f8e-47d6-b5a4-c3d2e1f0a9b8",
  "status": "running"
}
The secrets are stored and the run resumes. Keep polling until it’s terminal. If the connector rejects the credentials, the run blocks for credentials again — re-submit through this same endpoint (it overwrites the stored secret) and the agent retries the extractor.

Errors

StatusMeaning
400credentials missing or not a non-empty object; malformed JSON.
401API key missing or invalid.
404No such run, the migration isn’t in your account, or the run’s connection no longer exists.
409The run isn’t awaiting credentials (not blocked, or blocked on a question instead); connection_id doesn’t match the run; or no active credential request to answer yet — retry shortly.
429Rate limit hit — back off and retry.
500Server error.

Example

curl -X POST \
  https://app.vern.so/api/v1/migrations/c0a8012e-.../runs/d4c3b2a1-.../credentials \
  -H "x-api-key: $VERN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "credentials": { "client_id": "…", "client_secret": "…", "refresh_token": "…" }
  }'

Next