Skip to main content

AdminApi

Struct AdminApi 

Source
pub struct AdminApi { /* private fields */ }
Expand description

Platform admin: tenants, audit, reconciliation, DLQ, analytics

Implementations§

Source§

impl AdminApi

Source

pub async fn add_android_testers( &self, body: &AddAndroidTestersRequest, ) -> Result<AddAndroidTestersResponse>

Add addresses to the roster by hand

Super-admin only. Addresses reach the owner from the Play console and from people who write directly, so the landing form is not the only door. Partial success is normal: each address lands in exactly one of the three lists and the call is still 200.

POST /api/v1/admin/testers/android

Required scopes: admin.

Source

pub async fn admin_analytics_agents( &self, params: &AdminAnalyticsAgentsParams, ) -> Result<AgentAnalyticsSummary>

Platform-wide agent analytics

GET /api/v1/admin/analytics/agents

Required scopes: admin.

Source

pub async fn admin_analytics_events( &self, params: &AdminAnalyticsEventsParams, ) -> Result<AdminAnalyticsEventsResponse>

Platform-wide event analytics

GET /api/v1/admin/analytics/events

Required scopes: admin.

Source

pub async fn admin_analytics_overview( &self, params: &AdminAnalyticsOverviewParams, ) -> Result<AdminAnalyticsOverviewResponse>

Platform-wide analytics overview

GET /api/v1/admin/analytics/overview

Required scopes: admin.

Source

pub async fn admin_data_explorer_raw_keys( &self, params: &AdminDataExplorerRawKeysParams, ) -> Result<AdminDataExplorerRawKeysResponse>

Full KV scan (admin diagnostic)

Dangerous: full DB key scan. Admin-only. Use the namespace-scoped endpoints under /admin/data-explorer/* for normal browsing.

GET /api/v1/admin/data-explorer/raw-keys

Required scopes: admin.

Source

pub fn admin_data_explorer_raw_keys_all<'a>( &'a self, params: &'a AdminDataExplorerRawKeysParams, ) -> impl Stream<Item = Result<AdminDataExplorerRawKeysResponseKey>> + 'a

Stream every item returned by adminDataExplorerRawKeys, following the cursor cursor until the server reports no further pages.

Source

pub async fn admin_delete_o_auth_provider( &self, provider: &OAuthLoginProviderConfigStatusProvider, ) -> Result<OAuthLoginProviderConfigDeleted>

Remove OAuth login provider (super-admin)

DELETE /api/v1/admin/oauth-login-providers/{provider}

Required scopes: admin.

Source

pub async fn admin_get_landing_config(&self) -> Result<Map<String, Value>>

Admin: get landing-page featured-agent config

GET /api/v1/admin/config/landing

Required scopes: admin.

Source

pub async fn admin_get_model_catalog(&self) -> Result<Map<String, Value>>

Admin: get curated model catalog

GET /api/v1/admin/config/model-catalog

Required scopes: admin.

Source

pub async fn admin_get_model_catalog_seed(&self) -> Result<Map<String, Value>>

Admin: model catalog default seed

GET /api/v1/admin/config/model-catalog/seed

Required scopes: admin.

Source

pub async fn admin_get_model_pricing(&self) -> Result<Map<String, Value>>

Admin: live per-model pricing (synced from the configured provider)

GET /api/v1/admin/config/model-pricing

Required scopes: admin.

Source

pub async fn admin_get_o_auth_provider( &self, provider: &OAuthLoginProviderConfigStatusProvider, ) -> Result<OAuthLoginProviderConfigStatus>

Get configured OAuth login provider (super-admin)

Returns provider config with the client_secret masked (last 4 chars only). Returns {configured: false} for unconfigured providers.

GET /api/v1/admin/oauth-login-providers/{provider}

Required scopes: admin.

Source

pub async fn admin_get_reconciliation( &self, tenant_id: &str, ) -> Result<AdminGetReconciliationResponse>

Get last stored cost-reconciliation result for a tenant

GET /api/v1/admin/reconciliation/{tenantId}

Required scopes: admin.

Source

pub async fn admin_get_voice_config(&self) -> Result<Map<String, Value>>

Admin: get default voice (STT/TTS) config

GET /api/v1/admin/config/voice

Required scopes: admin.

Source

pub async fn admin_get_voice_presets(&self) -> Result<Map<String, Value>>

Admin: get per-model voice presets

GET /api/v1/admin/config/voice-presets

Required scopes: admin.

Source

pub async fn admin_list_tools(&self) -> Result<AdminListToolsResponse>

Admin: enumerate available built-in tools

GET /api/v1/admin/tools

Required scopes: admin.

Source

pub async fn admin_list_webhook_dlq( &self, ) -> Result<AdminListWebhookDLQResponse>

List dead-lettered webhook deliveries

GET /api/v1/admin/webhooks/dlq

Required scopes: admin.

Source

pub async fn admin_put_landing_config( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Admin: set landing-page featured-agent config

PUT /api/v1/admin/config/landing

Required scopes: admin.

Source

pub async fn admin_put_model_catalog( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Admin: replace curated model catalog

PUT /api/v1/admin/config/model-catalog

Required scopes: admin.

Source

pub async fn admin_put_o_auth_provider( &self, provider: &OAuthLoginProviderConfigStatusProvider, body: &OAuthLoginProviderConfigUpdate, ) -> Result<OAuthLoginProviderConfigUpdateResponse>

Set/update OAuth login provider (super-admin)

Merge semantics: omitting client_secret keeps the existing one (so toggling enabled doesn’t require re-pasting the secret). First-time PUT requires both client_id and client_secret. Stored encrypted at rest.

PUT /api/v1/admin/oauth-login-providers/{provider}

Required scopes: admin.

Source

pub async fn admin_put_voice_config( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Admin: set default voice config

PUT /api/v1/admin/config/voice

Required scopes: admin.

Source

pub async fn admin_put_voice_presets( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Admin: set per-model voice presets

PUT /api/v1/admin/config/voice-presets

Required scopes: admin.

Source

pub async fn admin_replay_webhook_dlq( &self, event_id: &str, ) -> Result<AdminReplayWebhookDLQResponse>

Replay a dead-lettered webhook event

POST /api/v1/admin/webhooks/dlq/{eventId}/replay

Required scopes: admin.

Source

pub async fn create_admin_blog_post( &self, body: &CreateAdminBlogPostRequest, ) -> Result<CreateAdminBlogPostResponse>

Write a post by hand

source is stamped manual and cannot be set by the caller. The slug is derived from the title and made unique; status defaults to draft.

POST /api/v1/admin/blog/posts

Required scopes: admin.

Source

pub async fn create_admin_provider( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Create custom provider

POST /api/v1/admin/providers

Required scopes: admin.

Source

pub async fn create_tenant(&self, body: &Map<String, Value>) -> Result<Tenant>

Create new tenant

POST /api/v1/admin/tenants

Required scopes: admin.

Source

pub async fn delete_admin_blog_post( &self, post_id: &str, ) -> Result<DeleteAdminBlogPostResponse>

Delete a post

DELETE /api/v1/admin/blog/posts/{postId}

Required scopes: admin.

Source

pub async fn delete_admin_integration_o_auth_provider( &self, provider: &GetAdminIntegrationOAuthProviderProvider, ) -> Result<DeleteAdminIntegrationOAuthProviderResponse>

Remove one provider’s stored OAuth credentials

Deletes the record outright — this is the only way to clear a stored credential, since the PUT treats a blank value as “keep”. Idempotent: deleting a provider that has nothing stored is still 200.

DELETE /api/v1/admin/integration-oauth-providers/{provider}

Required scopes: admin.

Source

pub async fn delete_admin_llm_default( &self, provider_id: &str, ) -> Result<DeleteAdminLLMDefaultResponse>

Remove the platform API key for a provider

Drops the stored platform key. The PROVIDER survives — this is the key, not the definition; DELETE /api/v1/admin/providers/{providerId} is the other one, and it removes a custom provider outright.

Answers configured: false for the provider, which is the same field GET /api/v1/admin/llm-defaults reports per provider, so the caller can apply the answer without a re-read.

DELETE /api/v1/admin/llm-defaults/{providerId}

Required scopes: admin.

Source

pub async fn delete_admin_provider( &self, provider_id: &str, ) -> Result<DeleteAdminProviderResponse>

Remove a custom provider (super-admin, fresh MFA)

Removes a CUSTOM provider and its settings. A built-in provider is not deletable and answers 404 here — that 404 means “no such CUSTOM provider”, not “no such provider”, which is worth knowing before reading it as a routing mistake.

Gated on a fresh MFA challenge because it is irreversible: the definition and its settings are deleted outright, not disabled. To stop using a provider without losing it, PATCH enabled: false instead. To drop the platform API KEY while keeping the provider, use DELETE /api/v1/admin/llm-defaults/{providerId} — a different route with a different subject.

DELETE /api/v1/admin/providers/{providerId}

Required scopes: admin.

Source

pub async fn delete_android_tester( &self, email: &str, ) -> Result<DeleteAndroidTesterResponse>

Take one address off the roster

Super-admin only. The address is a path segment, so it arrives percent-encoded.

DELETE /api/v1/admin/testers/android/{email}

Required scopes: admin.

Source

pub async fn generate_admin_blog_post( &self, ) -> Result<GenerateAdminBlogPostResponse>

Run the authoring agent now and create a post

Generates immediately, ignoring frequency — this is the operator’s manual trigger, not a schedule nudge. Whether the result lands published or as a draft follows the stored auto_publish.

A generation that FAILS is 422, not a 200 carrying an error field, so a client reads the status. Success is 201.

POST /api/v1/admin/blog/generate

Required scopes: admin.

Source

pub async fn get_admin_blog_config(&self) -> Result<GetAdminBlogConfigResponse>

Get the blog’s authoring configuration

Super-admin only. Wrapped in {config} rather than returned bare — the whole blog surface uses envelopes.

GET /api/v1/admin/blog/config

Required scopes: admin.

Source

pub async fn get_admin_integration_o_auth_provider( &self, provider: &GetAdminIntegrationOAuthProviderProvider, ) -> Result<GetAdminIntegrationOAuthProviderResponse>

Read one provider’s stored OAuth credentials (secret masked)

The response has two shapes and a client must handle both. With nothing stored it is the three-field form — {provider, enabled: false, configured: false} — and client_id, client_secret_hint and scopes are ABSENT, not null. With a record stored, all six are present.

The secret is never echoed. client_secret_hint is the last four characters behind dots, enough for an operator to confirm which credential is stored without seeing it, and it is null when the stored secret is empty.

GET /api/v1/admin/integration-oauth-providers/{provider}

Required scopes: admin.

Source

pub async fn get_admin_llm_defaults( &self, ) -> Result<GetAdminLLMDefaultsResponse>

List platform API keys (masked)

GET /api/v1/admin/llm-defaults

Required scopes: admin.

Source

pub async fn get_admin_pricing(&self) -> Result<Value>

Get pricing configuration

GET /api/v1/admin/config/pricing

Required scopes: admin.

Source

pub async fn get_admin_provider( &self, provider_id: &str, ) -> Result<Map<String, Value>>

Get single provider

GET /api/v1/admin/providers/{providerId}

Required scopes: admin.

Source

pub async fn get_admin_stats(&self) -> Result<GetAdminStatsResponse>

Aggregate usage stats

GET /api/v1/admin/stats

Required scopes: admin.

Source

pub async fn get_admin_trace( &self, trace_id: &str, ) -> Result<GetAdminTraceResponse>

Trace delegation chain

GET /api/v1/admin/trace/{traceId}

Required scopes: admin.

Source

pub async fn get_audit_for_target( &self, target_id: &str, params: &GetAuditForTargetParams, ) -> Result<Value>

Get audit entries for a specific target

GET /api/v1/admin/audit/{targetId}

Required scopes: admin.

Source

pub async fn get_conformity_report(&self) -> Result<Map<String, Value>>

EU AI Act conformity report

GET /api/v1/admin/conformity-report

Required scopes: admin.

Source

pub async fn get_immutable_audit( &self, params: &GetImmutableAuditParams, ) -> Result<GetImmutableAuditResponse>

Immutable audit log

GET /api/v1/admin/immutable-audit

Required scopes: admin.

Source

pub async fn get_maintenance_state(&self) -> Result<MaintenanceState>

Full maintenance record

The whole record, including who turned it on and when — the audit trail the public status deliberately omits. Super-admin only, and a caller on the synthetic default tenant is 401 rather than 403.

GET /api/v1/admin/maintenance

Required scopes: admin.

Source

pub async fn get_platform_economics( &self, params: &GetPlatformEconomicsParams, ) -> Result<PlatformEconomics>

Platform revenue, host cost and margin

Stripe subscriptions against real DigitalOcean spend, with the computed margin. Super-admin only.

Served from a short-lived cache; cache says whether this response was a hit, a miss, or a forced recomputation. A Stripe or provider outage does not fail the call — the affected block carries error and the rest is still served, so a partial answer is never mistaken for zeros.

GET /api/v1/admin/economics

Required scopes: admin.

Source

pub async fn get_tenant(&self, tenant_id: &str) -> Result<Tenant>

Get tenant details

GET /api/v1/admin/tenants/{tenantId}

Required scopes: admin.

Source

pub async fn get_tenant_mef_config( &self, tenant_id: &str, ) -> Result<TenantMefConfigResponse>

One tenant’s mission-framework overrides, and what they resolve to

Answers both layers at once: mef_config is what an operator stored for this tenant, effective is what the runtime will actually do. They differ whenever the platform is the deciding factor — with the mission service absent, every effective flag is false no matter what the tenant record says, so an operator reading only mef_config sees settings that do nothing.

mef_config is null when nothing is overridden, not an empty object.

GET /api/v1/admin/tenants/{tenantId}/mef-config

Required scopes: admin.

Source

pub async fn get_tenant_usage( &self, tenant_id: &str, params: &GetTenantUsageParams, ) -> Result<GetTenantUsageResponse>

Get tenant usage metrics

GET /api/v1/admin/tenants/{tenantId}/usage

Required scopes: admin.

Source

pub async fn internal_verify_domain(&self) -> Result<Map<String, Value>>

Internal domain verification

GET /api/v1/internal/verify-domain

Source

pub async fn list_admin_blog_posts(&self) -> Result<ListAdminBlogPostsResponse>

List every post, drafts included

The admin view: unlike the public blog read, drafts are included. Unpaged.

GET /api/v1/admin/blog/posts

Required scopes: admin.

Source

pub async fn list_admin_domain_health( &self, ) -> Result<ListAdminDomainHealthResponse>

Every tenant’s custom domain, worst first

The order is the product. Rows are sorted by problem severity — failed, then drift, then renewal_due, then pending, then healthy — so an operator’s eye lands on what is broken. A client that re-sorts alphabetically throws that away and should sort back, or not sort at all.

Tenants with no custom domain are omitted entirely, so count is the number of configured domains and not the number of tenants.

Bounded: the tenant registry scan takes at most 5000 entries in one pass and is not paged, so on a platform past that size this list is silently partial.

GET /api/v1/admin/domains/health

Required scopes: admin.

Source

pub async fn list_admin_integration_o_auth_providers( &self, ) -> Result<ListAdminIntegrationOAuthProvidersResponse>

Which integration providers an operator has configured

Super-admin only, and never returns a secret — provider id, an enabled bit, and whether credentials exist at all. The dashboard uses it to decide which connector rows need a “Configure” call to action.

Distinct from /api/v1/integrations/catalog, which is tenant-facing and lists every known connector regardless of OAuth-readiness.

The list is the SUPPORTED set, not the stored set: every supported provider appears, with configured: false where nothing is stored. So an empty result means the supported set is empty, never that nothing is configured.

GET /api/v1/admin/integration-oauth-providers

Required scopes: admin.

Source

pub async fn list_admin_providers(&self) -> Result<ListAdminProvidersResponse>

List providers with admin settings

GET /api/v1/admin/providers

Required scopes: admin.

Source

pub async fn list_android_testers( &self, params: &ListAndroidTestersParams, ) -> Result<ListAndroidTestersResponse>

The Android closed-testing roster

Super-admin only. The addresses the owner works from when adding people to the Play group. count, not_yet_emailed and given_up describe THIS PAGE, not the whole roster: all three are computed over the rows returned, so a roster longer than limit under-reports until every page is walked with cursor. not_yet_emailed counts rows no letter has gone to; given_up counts the ones the backfill has stopped retrying after repeated refusals, which need an eye rather than another pass.

GET /api/v1/admin/testers/android

Required scopes: admin.

Source

pub fn list_android_testers_all<'a>( &'a self, params: &'a ListAndroidTestersParams, ) -> impl Stream<Item = Result<AndroidTester>> + 'a

Stream every item returned by listAndroidTesters, following the cursor cursor until the server reports no further pages.

Source

pub async fn list_feedback( &self, params: &ListFeedbackParams, ) -> Result<ListFeedbackResponse>

The reports inbox

Every report from every tenant, newest first. Super-admin only. new_count counts the unresolved reports in the returned set, so a filtered list does not silently under-report the backlog.

GET /api/v1/admin/feedback

Required scopes: admin.

Source

pub async fn list_tenants(&self) -> Result<ListTenantsResponse>

List all tenants (super admin only)

GET /api/v1/admin/tenants

Required scopes: admin.

Source

pub async fn purge_admin_tenant( &self, tenant_id: &str, ) -> Result<PurgeAdminTenantResponse>

Purge tenant

DELETE /api/v1/admin/tenants/{tenantId}

Required scopes: admin.

Source

pub async fn query_audit_log( &self, params: &QueryAuditLogParams, ) -> Result<Value>

Query admin audit log

GET /api/v1/admin/audit

Required scopes: admin.

Source

pub async fn reactivate_tenant(&self, tenant_id: &str) -> Result<Value>

Reactivate a suspended tenant

PUT /api/v1/admin/tenants/{tenantId}/reactivate

Required scopes: admin.

Source

pub async fn set_admin_integration_o_auth_provider( &self, provider: &GetAdminIntegrationOAuthProviderProvider, body: &SetAdminIntegrationOAuthProviderRequest, ) -> Result<SetAdminIntegrationOAuthProviderResponse>

Store or update one provider’s OAuth credentials

WRITE SEMANTICS: merges, and the merge is what makes the route usable. An omitted or blank client_id or client_secret keeps the stored one, so an operator can flip enabled or rotate scopes WITHOUT re-pasting a secret they cannot read back. Blank counts as omitted here: a whitespace-only value does not clear anything.

The consequence is that there is no way to clear a credential through this route — DELETE the provider instead.

A FIRST write still needs both: with no stored record and either missing, the answer is 400. enabled defaults to true on a first write and otherwise keeps its stored value. A present scopes REPLACES the stored list.

The response is the short form, not the record: {provider, enabled, configured: true}, with no echo of the credentials just written.

PUT /api/v1/admin/integration-oauth-providers/{provider}

Required scopes: admin.

Source

pub async fn set_admin_llm_default( &self, provider_id: &str, body: &SetAdminLLMDefaultRequest, ) -> Result<SetAdminLLMDefaultResponse>

Set platform API key

PUT /api/v1/admin/llm-defaults/{providerId}

Required scopes: admin.

Source

pub async fn set_admin_model_config( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Set default model config

PUT /api/v1/admin/llm-defaults/model-config

Required scopes: admin.

Source

pub async fn set_maintenance_state( &self, body: &SetMaintenanceStateRequest, ) -> Result<MaintenanceState>

Turn maintenance mode on or off (super-admin)

Undocumented until now, while the GET beside it was described in full — so a generated client could READ the maintenance state and had no way to change it. The web has been calling this all along (lib/hooks/use-maintenance-mode.ts).

Answers the whole record back, the same shape the GET serves, so a client need not re-read to learn enabled_at and enabled_by_email.

WRITE SEMANTICS: replaces. The record is rebuilt from this body and written whole; nothing is read first. Turning maintenance ON without a message DROPS the message a previous ON had set, and turning it OFF wipes the message unconditionally, keeping only the timestamp and the actor so the audit trail still shows who closed the window. enabled_at and enabled_by_email are stamped on EVERY call, including one that changes nothing.

PUT /api/v1/admin/maintenance

Required scopes: admin.

Source

pub async fn suspend_tenant( &self, tenant_id: &str, body: &SuspendTenantRequest, ) -> Result<Value>

Suspend a tenant

PUT /api/v1/admin/tenants/{tenantId}/suspend

Required scopes: admin.

Source

pub async fn sync_provider_models( &self, provider_id: &str, ) -> Result<SyncProviderModelsResponse>

Pull one provider’s model list into the catalogue

Asks the provider what models it offers and MERGES the result into the platform catalogue. Additive only — nothing is removed, so a model the provider has withdrawn stays in the catalogue until it is deleted deliberately.

CUSTOM providers only: the 404 means “no custom provider with that id”, so a built-in provider id is also 404 here. added counts new entries, scanned is the provider’s reported inventory, and total is the catalogue size after the merge — so added is zero on a run that changed nothing, which is the normal result of a second run.

POST /api/v1/admin/providers/{providerId}/sync-models

Required scopes: admin.

Source

pub async fn update_admin_blog_config( &self, body: &UpdateAdminBlogConfigRequest, ) -> Result<UpdateAdminBlogConfigResponse>

Update the blog’s authoring configuration

WRITE SEMANTICS: merges. The body is spread over the stored record, so an omitted field keeps its value.

One field is not a plain merge: setting agent_id also pins agent_tenant_id to the CALLING tenant, because the cron that auto-writes posts runs without a request context and would otherwise have no tenant to run the agent in. Clearing agent_id to null nulls both. agent_tenant_id is therefore never sent by a client and never has to be — it is derived.

Answers the stored record, so a client sees what took effect.

PUT /api/v1/admin/blog/config

Required scopes: admin.

Source

pub async fn update_admin_blog_post( &self, post_id: &str, body: &UpdateAdminBlogPostRequest, ) -> Result<UpdateAdminBlogPostResponse>

Edit a post

WRITE SEMANTICS: merges. An omitted field keeps its value; tags present REPLACES the list.

Three things move on their own and a client should not try to send them. Editing the title or the body re-stamps source to manual, even on a post the agent wrote — the record then says who last shaped it rather than who started it. Changing the title mints a new unique slug, so a published post’s URL changes under it. And published_at follows status: it is stamped on the first transition to published and set back to null on draft, so a republished post carries a NEW timestamp rather than its original one.

PATCH /api/v1/admin/blog/posts/{postId}

Required scopes: admin.

Source

pub async fn update_admin_pricing( &self, body: &Map<String, Value>, ) -> Result<Value>

Update pricing configuration

PUT /api/v1/admin/config/pricing

Required scopes: admin.

Source

pub async fn update_admin_provider( &self, provider_id: &str, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Update provider

PATCH /api/v1/admin/providers/{providerId}

Required scopes: admin.

Source

pub async fn update_admin_tenant_settings( &self, tenant_id: &str, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Update tenant settings

PATCH /api/v1/admin/tenants/{tenantId}/settings

Required scopes: admin.

Source

pub async fn update_feedback_report_status( &self, report_id: &str, body: &UpdateFeedbackReportStatusRequest, ) -> Result<UpdateFeedbackReportStatusResponse>

Mark one feedback report resolved, or reopen it

Only the exact string resolved resolves a report; every other value sets it to new. There is no validation and no error path: "Resolved", "closed", a typo, a missing status, or a body that is not JSON at all are each accepted with 200 and REOPEN a resolved report. A client must send the literal value and must not rely on being told when it did not.

WRITE SEMANTICS: replaces the status field only; nothing else on the report is touched.

PATCH /api/v1/admin/feedback/{reportId}

Required scopes: admin.

Source

pub async fn update_tenant_mef_config( &self, tenant_id: &str, body: &UpdateTenantMefConfigRequest, ) -> Result<TenantMefConfigResponse>

Set or clear one tenant’s mission-framework overrides

WRITE SEMANTICS: merges, per key. Only the four known keys are read; a key the body omits keeps its stored value, and a key sent as null CLEARS that override so the flag falls back to the platform default. Unknown keys are ignored silently rather than rejected.

A non-boolean, non-null value for a known key is 422. Note the title on that one is ValidationError without a space, unlike the Validation Error used elsewhere on this surface.

When clearing the last override leaves nothing set, the whole mef_config is dropped rather than stored as {} — a later read answers null. And every accepted request writes: even a body that changes nothing stamps a new updated_at on the tenant record.

Answers the same body as the GET, so a client sees both the stored overrides and what they now resolve to.

PATCH /api/v1/admin/tenants/{tenantId}/mef-config

Required scopes: admin.

Source

pub async fn update_tenant_plan( &self, tenant_id: &str, body: &UpdateTenantPlanRequest, ) -> Result<UpdateTenantPlanResponse>

Set a tenant’s plan (super-admin)

The operator’s manual plan grant, undocumented while GET, PATCH and DELETE on this same path were described. It is not a general tenant update: plan is required and it is what the route is for.

WRITE SEMANTICS: mixed. The write is a compare-and-set MERGE onto the current record, so name, slug and quota_overrides keep their stored values when omitted. plan and quotas do not: both are written on every call, and omitting quotas REPLACES the tenant quotas with the resolved plan defaults rather than leaving them alone. A caller raising one dimension must send quota_overrides, not quotas.

quotas REPLACES the plan’s quotas for this tenant. quota_overrides is the durable one — a partial grant that survives a later Stripe subscription change, where a plain quotas write does not. When a tenant’s plan keeps reverting, the override is the field that makes it stick, and it must be set BEFORE the plan is put back, not after.

Granting any paid plan clears a stale billing_status (a “cancelled” left over from an earlier Stripe cancellation becomes “active”); a downgrade to free leaves the status alone, since free is never gated.

PUT /api/v1/admin/tenants/{tenantId}

Required scopes: admin.

Trait Implementations§

Source§

impl Clone for AdminApi

Source§

fn clone(&self) -> AdminApi

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AdminApi

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more