Skip to Content
We are live but in Staging 🎉
PipelinesCLI Guidedodil data credential

dodil data credential

Store credentials + run the OAuth flow. Aliased as dodil data cred. The CLI exposes three of the six surviving operations — list, delete and refresh live on the API.

Preview — credentials are paired with external sources, which are Preview. The production internal-S3 path needs no credential. Shapes below reflect today’s CLI; expect refinements.

Credentials are org-scoped. They can optionally link to a source_id via --source-id on oauth-exchange.

dodil data credential store

dodil data credential store [display-name]

Stores a credential. The CLI sends only the display name — it has no flags for provider, credential type, or the secret payload, and it does not prompt for them. The request goes out with display_name set and the credential_data oneof empty, so the result is a credential row with no usable secret.

For anything real, use the StoreCredential API directly, where you set provider, credential_type, and exactly one of access_key / oauth2 / api_key / service_account / pat:

curl -sS -X POST "https://api.data.dodil.io/admin/credentials" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "provider": "SOURCE_PROVIDER_GITHUB", "credentialType": "CREDENTIAL_TYPE_PAT", "displayName": "gh-readonly", "isPrimary": true, "pat": { "token": "ghp_...", "username": "svc-dodil" } }'

For OAuth providers, don’t use store at all — run oauth-url then oauth-exchange below, which stores the credential for you.

dodil data credential oauth-url

Stage 1 of the OAuth authorization-code flow. Asks K3 for a provider authorization URL you redirect your user to.

dodil data credential oauth-url -p PROVIDER_ID
FlagShortTypeDescription
--provider-id-pstringRequired. Provider key — normalized case-insensitively (see below)

Example:

dodil data credential oauth-url -p google_drive -o json # Response includes auth_url + state — redirect the user to auth_url

dodil data credential oauth-exchange

Stage 3 — exchange the OAuth code returned by the provider for stored credentials.

dodil data credential oauth-exchange \ -p PROVIDER_ID \ -c OAUTH_CODE \ [--redirect-uri URI] \ [--state STATE] \ [--source-id SOURCE_ID] \ [--display-name NAME]
FlagShortTypeDescription
--provider-id-pstringRequired. Same provider as oauth-url
--code-cstringRequired. Authorization code from the provider callback
--redirect-uristringSame URI passed to oauth-url
--statestringCSRF / correlation token (matches oauth-url’s state)
--source-idstringLink credential to an existing source
--display-namestringHuman-friendly name

Example — Google Drive:

# 1. Get authorization URL URL=$(dodil data credential oauth-url -p google_drive -o json | jq -r '.authUrl') open "$URL" # user authorizes; provider redirects to callback with ?code=... # 2. Exchange the code dodil data credential oauth-exchange \ -p google_drive \ -c "<oauth_code>" \ --redirect-uri "https://app.example.com/k3/oauth/callback" \ --display-name "gdrive-main"

Provider-ID input

The CLI normalizes provider IDs case-insensitively, with _ and - interchangeable:

  • google_drive
  • GOOGLE-DRIVE
  • source_provider_google_drive

All three resolve to SOURCE_PROVIDER_GOOGLE_DRIVE.

Operations not in the CLI today

OperationUse the API
ListCredentialsGET /admin/credentials — returns CredentialInfo only, never a payload
DeleteCredentialDELETE /admin/credentials/{credential_id}
RefreshOAuthTokenPOST /admin/credentials/{credential_id}/refresh

Operations that no longer exist

Two RPCs were retired and have no route, no replacement, and no CLI equivalent. Anything still calling them is broken:

RetiredWhyWhat to do instead
GetCredentialIt returned raw access/refresh tokens, API keys, service-account JSON and PATs — at viewer tier. A control plane whose job is to hold secrets in Vault must not offer an org-level RPC that reads them back in plaintext.Nothing reads a secret back. To renew an expired OAuth token, call RefreshOAuthToken, which refreshes it in place.
ValidateCredentialIt validated nothing: it echoed the stored is_valid — only ever written true — and stamped validated_at: now(), implying a live provider check it never performed.Treat is_valid on CredentialInfo as unverified. A real provider probe would be a new RPC; none exists yet.

See also