Skip to main content

Success messages

apiSuccessInterceptor resolves a message for successful requests and hands it to the configured ApiSuccessHandler. As with errors, the library presents nothing itself — the default handler discards the message until you supply an adapter for your UI kit.

provideHttpClient(withInterceptors([apiErrorInterceptor, apiSuccessInterceptor, retryInterceptor]));

Resolution rules

For each successful response, ApiRequestOptions.successMessage decides:

ValueResult
stringThat exact message
falseNo message, even if enabled globally
trueThe configured default for the request's method — including for GET
omitted (default)The method's default, but only for POST/PUT/PATCH/DELETE and only if defaultShowSuccessMessage

If a method has no configured default — GET with successMessage: true, for instance — the generic fallback 'Operation completed successfully.' is used.

Default messages

MethodDefault message
POSTCreated successfully.
PUTUpdated successfully.
PATCHUpdated successfully.
DELETEDeleted successfully.

Override any subset; the rest keep their built-ins:

provideApi({
baseUrl: 'https://api.example.com',
defaultSuccessMessages: {
post: 'Record created',
delete: 'Record deleted',
},
});

Turn the whole behaviour off with defaultShowSuccessMessage: false, and opt individual calls back in with successMessage: true or a string.

Presenting them

@Injectable()
export class ToastApiSuccessHandler extends ApiSuccessHandler {
private readonly toast = inject(MyToastService);

override handle(message: string): void {
this.toast.success(message, { life: 3000 });
}
}
src/app/app.config.ts
providers: [{ provide: ApiSuccessHandler, useClass: ToastApiSuccessHandler }];

Per-request control

// A specific message for this operation
this.api.put(`/orders/${id}`, order, { successMessage: 'Order updated' });

// Silence a background save
this.api.patch(`/drafts/${id}`, draft, { successMessage: false });

// Report a read, which normally says nothing
this.api.get<Report>('/reports/daily', { successMessage: 'Report refreshed' });

Translated messages

Messages are plain strings, so the package carries no i18n dependency. Either pass already-translated values into defaultSuccessMessages:

provideApi({
baseUrl: 'https://api.example.com',
defaultSuccessMessages: {
post: translate('api.created'),
put: translate('api.updated'),
},
});

…or skip the defaults entirely and do the wording inside your handler, where the injector gives you access to your translation service:

@Injectable()
export class I18nApiSuccessHandler extends ApiSuccessHandler {
private readonly translate = inject(TranslateService);
private readonly toast = inject(MyToastService);

override handle(key: string): void {
this.toast.success(this.translate.instant(key));
}
}

With that arrangement, pass translation keys as the messages rather than prose.