selan.ai

Docs · Google Vertex

Connect Google Vertex

Run Claude on a Google Cloud project you own, so the inference lands on your Google invoice instead of ours. Six steps, three of them commands. For how connecting a provider fits together, start at the docs.

What you are setting up

Selan holds no key to your Google account. Instead you grant one Google service account (ours) a single role on a project you own, and we mint a short-lived token at the moment of each request. We store nothing long-lived, and you can revoke the grant in one command without involving us.

The account you grant is:

selan-vertex@selan-prod.iam.gserviceaccount.com

It has no privileges of its own anywhere. Everything it can do on your project comes from you, and it is deliberately not the identity Selan's own application runs as.

Use a project of its own. With a new, empty project, the role you grant reaches nothing else you run, and the Claude spend stays cleanly attributable on your bill. It also makes for a much shorter conversation with whoever approves access. Connecting your main production project works, and asks far more of you than it needs to.

The six steps

Replace YOUR_PROJECT throughout with the project id you are connecting. Steps 1, 2 and 5 happen in the Google Cloud console; 3, 4 and 6 are commands. The Selan dialog shows you 3 and 4 with your project already filled in.

1. Create a project and link billing.

gcloud projects create YOUR_PROJECT --name="Selan Vertex"

Then link a billing account to it in Billing. Vertex will refuse to serve a project with no billing attached, and the error does not say so in as many words.

2. Enable Claude in Model Garden.

Open Model Garden, search for Claude, open the model you want and press Enable. This is where you accept Anthropic's terms, and it is per project. A project that has not been through it has no Claude quota at all, which is the single most common reason a connection fails.

3. Switch the Vertex API on.

gcloud services enable aiplatform.googleapis.com --project YOUR_PROJECT

4. Grant Selan the one role it needs.

gcloud projects add-iam-policy-binding YOUR_PROJECT --member=serviceAccount:selan-vertex@selan-prod.iam.gserviceaccount.com --role=roles/aiplatform.user

5. Request Claude quota.

A new project starts at zero quota, and no command grants it. Open Quotas, filter on anthropic, and request an increase on global_online_prediction_requests_per_base_model for each Claude model you intend to use. Quota is granted per model, so one grant does not cover the others. Google reviews the request, so it is not instant.

6. Sync the enablement across Google's regions.

Step 2 records what you accepted, but not everywhere it has to be recorded. Global is not a place — it is a router that spreads your requests over about a dozen regional backends, and each one keeps its own copy of which models your project may use. Until those copies agree, some of your requests land on a backend that has never heard of the model, and Google answers 404 or 403 for a model that worked a second earlier. On one project we measured this at 14% of its traffic.

The fix is Google's own: one :enableModel call per region, which makes each backend re-read your allowlist. It changes nothing except what you already chose in step 2 — it cannot enable a model you never accepted, grant quota, or read anything — and it is idempotent, so re-running it is safe and is also how you check the current state.

We do not do this for you, by choice rather than by inability. The service account you grant us could: roles/aiplatform.user turns out to be enough. But that role exists so we can run inference on your project, and reconfiguring the project is a different kind of act — it should be one you perform and can see in your own audit log. So we keep to inference, and hand you the script.

curl -O https://selan.ai/vertex-sync.sh
less vertex-sync.sh          # it is short, and says what each call does
chmod +x vertex-sync.sh

./vertex-sync.sh --show YOUR_PROJECT   # print the calls, send none of them
./vertex-sync.sh YOUR_PROJECT          # send them

--show is there so you never have to take the paragraph above on trust: it prints the exact requests and makes none of them. Read it, then decide. If you would rather not run a downloaded script at all, the loop below is the same thing inline:

PROJECT=YOUR_PROJECT
TOKEN=$(gcloud auth print-access-token)

for LOC in global us eu us-east5 us-east1 us-central1 us-west4 us-south1 \
           europe-west1 europe-west4 europe-north1 asia-southeast1; do
  case $LOC in
    global) HOST=aiplatform.googleapis.com ;;
    us|eu)  HOST=aiplatform.$LOC.rep.googleapis.com ;;
    *)      HOST=$LOC-aiplatform.googleapis.com ;;
  esac
  for MODEL in claude-opus-5 claude-sonnet-5 claude-haiku-4-5@20251001; do
    curl -s -o /dev/null -w "$LOC $MODEL %{http_code}\n" -X POST \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -H "x-goog-user-project: $PROJECT" \
      "https://$HOST/v1beta1/projects/$PROJECT/publishers/anthropic/models/$MODEL:enableModel" \
      -d '{}'
  done
done

Every line should read 200. The region travels in the hostname rather than the path, which is the whole mechanism — the list of hosts is the list of backends, and leaving one out leaves exactly that backend stale. Add any model you intend to use to the inner list: a model you never enable here keeps failing intermittently however much quota it has.

Two refusals here are worth telling apart, because the status cannot. Publisher Model […] not found means Google does not offer that model in that region, which is expected and harmless. No entitlements… means this project never accepted the model in Model Garden — that one is step 2, and no amount of re-running fixes it.

This is a workaround, not a setting. Google has confirmed the routing fault and is fixing it at their end, after which step 6 stops being necessary. Having run it does no harm, and we will say so here when it can be dropped.

Claude 5 models and data sharing

Some models in the Claude 5 generation, Fable 5.1 among them, will not serve at all until you have separately told Google you accept data sharing with Anthropic. Without it every request is refused, in every region, whatever steps 2 and 6 say:

403  Access to this model requires data sharing to be enabled for publisher 'anthropic'.

This one we do not do for you, and we will not advise you on it. It is a decision about your own prompts and outputs, so read Google's description of what it covers and decide for yourself. If you do accept it, it takes the same per-region fanout as step 6 — set on global alone it appears to succeed and changes nothing:

PROJECT=YOUR_PROJECT
MODEL=claude-fable-5-1
TOKEN=$(gcloud auth print-access-token)

for LOC in global us eu us-east5 us-east1 us-central1 us-west4 us-south1 \
           europe-west1 europe-west4 europe-north1 asia-southeast1; do
  case $LOC in
    global) HOST=aiplatform.googleapis.com ;;
    us|eu)  HOST=aiplatform.$LOC.rep.googleapis.com ;;
    *)      HOST=$LOC-aiplatform.googleapis.com ;;
  esac
  curl -s -o /dev/null -w "$LOC %{http_code}\n" -X POST \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -H "x-goog-user-project: $PROJECT" \
    "https://$HOST/v1beta1/projects/$PROJECT/locations/$LOC/publishers/anthropic/models/$MODEL:setPublisherModelConfig" \
    -d '{"publisherModelConfig":{"dataSharingEnabledProvider":"ANTHROPIC"},
         "updateMask":"dataSharingEnabledProvider"}'
done

200 is done and 409 is already done, so both are fine. Keep updateMask in the body: without it Google replaces that model's whole configuration rather than the one field, which quietly switches off any request logging you had set up.

Accepting data sharing is not the same as having quota. A model can clear this gate and still answer 429, which is step 5 and nothing to do with anything else on this page.

Connecting it in Selan

In Selan, open Tokens → Add token and choose Google Vertex as the provider. Enter the project id, choose a location, and press Add.

Add is not a save button. It first runs one real token of inference against your project, and if anything is missing it names the step to go back to instead of showing a status code. We store nothing unless that call succeeds.

LocationWhat it means
Global Google routes to wherever there is capacity. It has the best availability and no price premium, and it is the only tier that carries every current Claude model. Choose this unless you have a reason not to.
United States Requests stay within US regions. Google charges a 10% premium over global.
European Union Requests stay within EU regions. Google charges a 10% premium over global.

We deliberately do not offer specific regions such as europe-west1. Google serves Claude from them, but only up to older models. Picking one would build a connection that fails on exactly the models you are most likely to ask for.

When it refuses

Each refusal names the step that is missing. These are the six you are likely to see.

What Selan saysWhat to do
…has no Claude quota yet Step 5, and usually step 2 before it. This is the ordinary first attempt, and the wait is Google's, not ours.
The Vertex AI API is not switched on for… Step 3. The command is idempotent, so running it again is safe.
…has not granted Selan access Step 4. Check the project id in the command matches the one you typed.
Google has no Claude in location for… Google does not serve the model on that tier. Switch the location to Global.
Works, then fails, then works again Step 6. An intermittent 404 or 403 on a model that plainly exists is Google's routing rather than your project, and it does not settle on its own.
…requires data sharing to be enabled A Claude 5 model with a consent step of its own. See data sharing above — that one is yours to decide.

Turning it off

Remove the connection in Selan, or revoke the grant on your side. Either one stops it. Revoking on your side is absolute, and does not depend on us doing anything:

gcloud projects remove-iam-policy-binding YOUR_PROJECT --member=serviceAccount:selan-vertex@selan-prod.iam.gserviceaccount.com --role=roles/aiplatform.user

Selan stores no key for your Google account, so there is nothing left behind to rotate or expire. The next request fails to authenticate, and the connection stops being used.