useCapxulImageUpload
Mutation hook that uploads an image blob and binds it as the profile image or an organization logo in one step.
Uploads an image and records it as the signed-in user's profile image or an
organization logo — the whole upload → record sequence as one mutation. The
resolved serving URL then appears on
useCapxulProfile (imageUrl) or on
the organization read (logoUrl).
Serving URLs are not stable links
The returned url is resolved at read time and is not a long-lived stable link. Re-read it from
the profile or organization queries; do not persist it.
Import
import { useCapxulImageUpload } from "@capxul/sdk-react";Usage
"use client";
import { useCapxulImageUpload } from "@capxul/sdk-react";
function ProfileImagePicker() {
const upload = useCapxulImageUpload();
return (
<input
type="file"
accept="image/jpeg,image/png,image/webp"
disabled={upload.isPending}
onChange={(event) => {
const file = event.target.files?.[0];
if (file) upload.mutate({ blob: file, target: { kind: "profile" } });
}}
/>
);
}For an organization logo, pass target: { kind: "orgLogo", orgId }. Recording
a logo requires spend authority in that organization, and replacing an image
deletes the previously stored blob.
Parameters
The hook itself takes no parameters. The mutation takes an ImageUploadInput:
| Field | Type | Description |
|---|---|---|
blob | Blob | The image bytes; the blob's MIME type is sent as the upload content type. |
target | { kind: "profile" } | { kind: "orgLogo"; orgId: string } | What the uploaded image becomes. |
The backend recording mutation is the validation boundary: the blob must
declare a image/jpeg, image/png, or image/webp content type and be at
most 5 MB.
Return type
import { type UseCapxulImageUploadReturn } from "@capxul/sdk-react";
// UseMutationResult<{ url: string | null }, CapxulError, ImageUploadInput>On success, data.url is the resolved serving URL for the recorded image.
The hook returns TanStack Query's UseMutationResult. The most-used fields:
| Field | Description |
|---|---|
mutate | Fire the mutation (fire-and-forget; pair with onSuccess/onError callbacks). |
mutateAsync | Fire the mutation and get a Promise of the result. Rejects with a CapxulError on failure. |
data | The mutation result (typed per hook, shown above). undefined until the first success. |
error | A CapxulError when the last attempt failed, otherwise null. |
isPending | true while the mutation is in flight. Use it to disable submit buttons. |
reset | Clear the mutation state (data, error) back to idle. |
Mutations do not retry by default. The full field list is in the
TanStack Query useMutation reference;
see also the TanStack Query integration guide.
Client-backed mutation hooks are safe to render while CapxulProvider
bootstraps. If one is fired before bootstrap finishes, mutateAsync rejects
with a CapxulError whose code is WRONG_STATE; applications do not need to
hide their route tree behind useCapxul(). Every shipped mutation hook is
client-backed — alpha.23 removed the one client-free hook
(useCapxulSwitchActingEntity, a documented no-op).
Cache behavior
On success this mutation invalidates the profile query
(["capxul", "profile"]) for a profile image, or every organizations query
(the ["capxul", "orgs"] prefix) for a logo.
Errors
Failures surface as a CapxulError on error /
thrown from mutateAsync — INVALID_INPUT when the blob is not an accepted
image type or exceeds 5 MB, a provider error when the upload POST itself
fails, and NOT_AUTHENTICATED / authority errors when the caller does not own
the target profile or lacks spend authority in the target organization.
Client method
This hook wraps client.media.uploadImage(blob) followed by
client.media.setProfileImage({ storageId }) or
client.media.setOrgLogo({ orgId, storageId }) on the core SDK.