invalid_credentials
The credentials supplied to a Connect call were rejected by the upstream channel.
When it fires
You called POST /v1/connect/{provider} (or one of its credentials sub-routes) with credentials that the upstream channel rejected. Common triggers:
- Wrong API key / secret pair (typo, copy-paste truncation, leading whitespace).
- Credentials issued for a different environment (sandbox key against the live API).
- Credentials revoked or rotated since you last saved them.
- For Booking.com / Hostaway / Guesty / OwnerRez: the user account does not have the right permission scope on the channel side.
- For username/password combinations: account is locked, password expired, or 2FA is now required and not handled.
This is distinct from unauthorized —unauthorized means your Repull key is bad; invalid_credentials means your Repull key is fine but the channel credentials you are trying to connect failed.
Response shape
Every Repull error follows the same envelope. The code is stable and safe to switch on.
{
"error": {
"code": "invalid_credentials",
"message": "<human-readable explanation of what went wrong>",
"docs_url": "https://repull.dev/docs/errors/invalid_credentials"
}
}How to fix
- Re-paste the credentials directly from the channel's admin UI — do not type them by hand.
- Trim leading/trailing whitespace before sending; many shells include a trailing newline on `pbpaste`/`xclip`.
- Verify the credentials work in the channel's own UI or curl example before sending them to /connect.
- For Booking.com: confirm the property has the “Connectivity API” role enabled in Extranet → Account → Manage your team.
- For Hostaway / Guesty / OwnerRez: rotate the key from the channel's API settings and try again.
- If you are storing credentials in env vars, log their length (not the value) to confirm they made it into the request intact.
Common gotchas
- Repull never stores invalid credentials. A failed connect attempt does not pollute the workspace — you can retry as many times as you want without cleanup.
- If the channel has a sandbox/test environment, make sure the credentials and the API endpoint match. Sending sandbox credentials to a live endpoint (or vice versa) is a common source of this error.
- For OAuth-based providers (Airbnb), this code does not apply — auth failures there fire as part of the Connect callback URL with an
errorquery parameter instead.
Examples
curl
# Bad: wrong account number
curl -X POST https://api.repull.dev/v1/connect/hostaway/credentials \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"accountId": "WRONG", "apiKey": "WRONG_KEY"}'
# HTTP/1.1 401 Unauthorized
# {
# "error": {
# "code": "invalid_credentials",
# "message": "Hostaway rejected the credentials: invalid account or key"
# }
# }
# Good
curl -X POST https://api.repull.dev/v1/connect/hostaway/credentials \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"accountId": "12345", "apiKey": "live_real_key"}'TypeScript
import { Repull } from '@repull/sdk'
const repull = new Repull({ apiKey: process.env.REPULL_KEY! })
try {
await repull.connect.hostaway.attach({
accountId: process.env.HOSTAWAY_ID!,
apiKey: process.env.HOSTAWAY_KEY!,
})
} catch (err: any) {
if (err.code === 'invalid_credentials') {
// Surface to the user — they need to fix the channel credentials,
// not your Repull key.
return { reason: 'channel_auth_failed', detail: err.message }
}
throw err
}If you're an AI agent
The Repull key is fine — the credentials the user gave you for the channel were rejected by the channel itself. Do NOT retry. Ask the user to re-paste their channel credentials, or to rotate them in the channel's admin UI.
Related
- Error reference — the full table of error codes
- Using Repull from AI agents — patterns for handling errors in agent loops
- unauthorized
- Connect (multi-channel)
- PMS Coverage
Hit an error that isn't covered? Email hello@repull.dev with the request id from the response headers.