Credentials — API Reference
Package: dodil.k3.source.v1 · Service: SourceService
Credentials are org-scoped (not bucket-scoped) and may optionally link to a source_id. Five credential types, discriminated by CredentialType and a oneof credential_data payload — see Core Concepts → Credential.
Preview — the entire Credentials API surface, including the OAuth flow, is paired with external sources, which are Preview. The production internal-S3 path requires no credential. Shapes below reflect today’s API; expect refinements.
| RPC | HTTP |
|---|---|
StoreCredential | POST /admin/credentials |
GetCredential | GET /admin/credentials/:credential_id |
ListCredentials | GET /admin/credentials |
DeleteCredential | DELETE /admin/credentials/:credential_id |
ValidateCredential | POST /admin/credentials/:credential_id/validate |
GetOAuthUrl | POST /admin/oauth/authorize |
ExchangeOAuthCode | POST /admin/oauth/token |
RefreshOAuthToken | POST /admin/credentials/:credential_id/refresh |
Secrets are stored in HashiCorp Vault behind K3.
ListCredentialsonly returnsCredentialInfo(no secret payload);GetCredentialreturns the full payload for the credential you own.
gRPC setup —
grpcurl, endpoints, reflection, and field-name casing — is covered once in Conventions → Using gRPC.
StoreCredential
Stores a credential directly. For OAuth providers, prefer the OAuth flow below — it handles redirect + code exchange end-to-end. Use this for API keys, PATs, service-account JSON keys, and access keys.
Request
HTTP
GitHub PAT variant:
curl -sS -X POST "https://k3.dev.dodil.io/admin/credentials" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "SOURCE_PROVIDER_GITHUB",
"credentialType": "CREDENTIAL_TYPE_PAT",
"displayName": "github-readonly",
"isPrimary": true,
"pat": { "token": "ghp_...", "username": "dodil-bot" }
}'External S3 access-key variant:
curl -sS -X POST "https://k3.dev.dodil.io/admin/credentials" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "SOURCE_PROVIDER_INTERNAL_S3",
"credentialType": "CREDENTIAL_TYPE_ACCESS_KEY",
"displayName": "external-s3",
"accessKey": {
"accessKeyId": "AKIA...",
"secretAccessKey": "wJalrXUt...",
"region": "us-east-1",
"endpoint": "https://s3.example.com"
}
}'Response
HTTP
{
"credentialId": "cred_a1b2..."
}GetCredential
Returns the credential’s CredentialInfo and (subject to authorization) its secret payload. Pass auto_refresh = true to refresh expired OAuth tokens before returning.
Request
HTTP
curl -sS "https://k3.dev.dodil.io/admin/credentials/cred_a1b2...?auto_refresh=true" \
-H "Authorization: Bearer $DODIL_TOKEN"Response
HTTP
{
"info": {
"credentialId": "cred_a1b2...",
"sourceId": "src_a1b2...",
"provider": "SOURCE_PROVIDER_GOOGLE_DRIVE",
"credentialType": "CREDENTIAL_TYPE_OAUTH2",
"displayName": "gdrive-main",
"isPrimary": true,
"isValid": true,
"createdAt": "1716840000000",
"updatedAt": "1716843600000",
"expiresAt": "1716847200000"
},
"oauth2": {
"accessToken": "ya29....",
"refreshToken": "1//...",
"expiresAt": "1716847200000",
"tokenType": "Bearer",
"scopes": ["https://www.googleapis.com/auth/drive.readonly"]
}
}ListCredentials
Returns CredentialInfo rows only — no secret payloads. Filter by source_id or provider.
Request
HTTP
All credentials for Google Drive:
curl -sS "https://k3.dev.dodil.io/admin/credentials?provider=SOURCE_PROVIDER_GOOGLE_DRIVE" \
-H "Authorization: Bearer $DODIL_TOKEN"All credentials linked to a specific source:
curl -sS "https://k3.dev.dodil.io/admin/credentials?source_id=src_a1b2..." \
-H "Authorization: Bearer $DODIL_TOKEN"Response
HTTP
{
"credentials": [
{
"credentialId": "cred_a1b2...",
"sourceId": "src_a1b2...",
"provider": "SOURCE_PROVIDER_GOOGLE_DRIVE",
"credentialType": "CREDENTIAL_TYPE_OAUTH2",
"displayName": "gdrive-main",
"isPrimary": true,
"isValid": true,
"createdAt": "1716840000000",
"updatedAt": "1716843600000",
"expiresAt": "1716847200000"
}
]
}DeleteCredential
Request
HTTP
curl -sS -X DELETE "https://k3.dev.dodil.io/admin/credentials/cred_a1b2..." \
-H "Authorization: Bearer $DODIL_TOKEN"Response
Empty (DeleteCredentialResponse {}).
ValidateCredential
Live-checks the credential against the provider. For OAuth, this typically calls a low-cost provider endpoint to verify the token is still good; for API keys / PATs, it makes a token-info or ping call.
Request
HTTP
curl -sS -X POST "https://k3.dev.dodil.io/admin/credentials/cred_a1b2.../validate" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"credentialId": "cred_a1b2..."
}'Response
HTTP
{
"isValid": true,
"errorMessage": "",
"validatedAt": "1716843600000"
}OAuth flow
Three RPCs, one per stage of the standard OAuth authorization-code flow:
GetOAuthUrl— your backend asks K3 for an authorization URL; K3 returns the URL with the right scopes + client ID for the provider.- User redirect — your frontend redirects the user to that URL; the user authorizes; the provider redirects back to your
redirect_uriwith?code=...&state=.... ExchangeOAuthCode— your backend hands the code back to K3, which exchanges it for tokens and stores them as a credential. Returns thecredential_id.
Later, RefreshOAuthToken refreshes expiring tokens — or use auto_refresh = true on GetCredential to do it implicitly.
GetOAuthUrl
Request
HTTP
curl -sS -X POST "https://k3.dev.dodil.io/admin/oauth/authorize" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "SOURCE_PROVIDER_GOOGLE_DRIVE",
"redirectUri": "https://app.example.com/k3/oauth/callback",
"scopes": ["https://www.googleapis.com/auth/drive.readonly"],
"state": "req-123"
}'Response
HTTP
{
"authUrl": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...",
"state": "req-123"
}ExchangeOAuthCode
Request
HTTP
curl -sS -X POST "https://k3.dev.dodil.io/admin/oauth/token" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "SOURCE_PROVIDER_GOOGLE_DRIVE",
"code": "<oauth_code>",
"redirectUri": "https://app.example.com/k3/oauth/callback",
"state": "req-123",
"displayName": "gdrive-main"
}'Response
HTTP
{
"credentialId": "cred_a1b2..."
}RefreshOAuthToken
Request
HTTP
curl -sS -X POST "https://k3.dev.dodil.io/admin/credentials/cred_a1b2.../refresh" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"credentialId": "cred_a1b2..."
}'Response
HTTP
{
"success": true,
"expiresAt": "1716847200000"
}See also
- Sources — link credentials to sources via
source_id - Core Concepts → Credential — the typed payload variants
- CLI Guide → credential —
dodil k3 credential store / oauth-url / oauth-exchange grpcurlreference — full flag set + reflection-disabled fallbacks