Patch Credential
Edit a team’s stored integration credential post-onboarding.
Required for credential rotation (token expired), repo URL drift
(the 2026-06-05 bleshinsky → AITaskerCo GitHub org transfer
left 5 Keystatic credentials pointing at the old URL — the
operator workaround was 5 raw SQL UPDATEs), and
content_paths updates without re-creating the row.
On success, writes a TeamAuditLog row with
action_type='integration_credential_updated' and a sanitized
diff (field NAMES only — token VALUES are never logged). No-op
patches (every key equals stored) skip the audit write.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Partial update to a team's stored IntegrationCredential.
Wire format
All fields are optional. Omitted fields keep their stored value.
The shape mirrors RFC 7396 (JSON Merge Patch) at the
extra_data level with two AITasker-specific tweaks:
- Sensitive fields preserved on blank. If a sensitive field
(
github_tokenfor Keystatic,app_password/application_passwordfor WordPress) is sent as an empty string orNone, the stored ENCRYPTED value is kept (post- migratione8b3encsec01the secret lives inaccess_token_encrypted, notextra_data). This pairs with the masked-placeholder UX on the edit form: stored secrets render asplaceholder="••••"and only submit when the user retypes them. Non-blank sensitive values are AES-256-GCM encrypted and written to the encrypted column; they NEVER land inextra_data. - Top-level shallow merge. Nested structures (e.g.
Keystatic's
content_pathsdict) are REPLACED wholesale when the patch contains them. Edit-form convention: post the full nested dict for any structured field touched.
See team_integration_service.merge_credential_extra_data for
the merge rules + encryption side-channel and unit tests.
Auth
PATCH requires team ownership — same gate as POST /config.
A credential_id that doesn't belong to the caller's team
returns 404, not 403, to prevent enumeration of other teams'
credential ids.