---
title: "Remove Provider Key"
method: DELETE
path: "/api/v1/billing/provider-keys/{provider}"
tags: ["authed"]
---

# Remove Provider Key

`DELETE /api/v1/billing/provider-keys/{provider}`

## Request

- Base URL: `https://api.teaflask.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.teaflask.com/api/v1/billing/provider-keys/{provider}`
- Auth: none declared

Withdraws the key entirely — the row goes, no sealed ciphertext
left at rest. The org's usage at that provider bills to its balance
again from the next run on; a probe still in flight for the removed
key settles as superseded and touches nothing.

## Path parameters

- `provider` 'anthropic' | 'openai' | 'openrouter', required: Whose API a model call dials — the dimension BYOK keys, probes, bounce classification, and platform-key selection all key on. The vocabulary is append-only and each new value arrives with its integration (probe + classifier + key-shape rule + a platform key unless BYOK-only), never ahead of it.

## Response `200`

Successful Response

- BillingResponse
  - `balance_microusd` integer, required: The prepaid balance that pays for model calls; it can fall below zero, for example after a card payment is disputed. In microusd: millionths of a US dollar (1,000,000 = $1.00).
  - `plan` 'free' | 'enterprise', required: Which plan an organization is on. What each plan entitles lives in src/plan_entitlements.py — the code map, never columns here.
  - `plan_entitlements` PlanEntitlementsView, required: What the organization's plan includes.
    - `sso_saml` boolean, required: Whether SAML single sign-on is included.
    - `support_tier` 'community' | 'dedicated', required: Who answers when the org needs help: the community channels, or a named human with an inbox (enterprise onboards manually — the tier travels with the contract).
    - `sla_tier` 'none' | 'uptime_99_9', required: What uptime the contract promises. NONE is best-effort — the free plan's honest answer, not a hidden 99.9.
  - `plan_source` 'manual' | 'aws_marketplace', nullable, required: Where Enterprise comes from: manual when it was set up directly with us, aws_marketplace when an AWS Marketplace contract is its only source; null on the free plan.
  - `billing_channel` 'direct' | 'aws_marketplace', required: How an organization pays (the CHECK's mirror): direct is cards and top-ups through us; aws_marketplace is an AWS Marketplace contract, billed by AWS.
  - `card_billing_available` boolean, required: Whether card payments and top-ups apply to this organization; false when it pays through AWS Marketplace.
  - `marketplace_licenses` MarketplaceLicenseView[], required: The organization's AWS Marketplace licenses, oldest first; empty when it has none.
    - `state` 'pending' | 'active' | 'ended', required: Where an AWS Marketplace license stands (the CHECK's mirror): pending until GetEntitlements first grants it, active while AWS grants it, ended once AWS stops — the day AWS says, never a guess of ours.
    - `expires_at` string, date-time, nullable, required: When the contract runs out; null when AWS gave no end date.
    - `ended_at` string, date-time, nullable, required: When AWS reported the contract ended; null while it has not.
    - `quantity` integer, nullable, required: How many units the contract grants; null when AWS gave no count.
    - `claimed_at` string, date-time, required: When the license was connected to this organization.
  - `alert` BillingAlertView, required: The organization's current money warning.
    - `kind` 'low_balance' | 'key_declined' | 'balance_exhausted' | 'welcome_credit_locked' | 'own_key_required', required: LOW_BALANCE warns while work still starts; KEY_DECLINED means work on that provider's models is refused or skipped until the key is updated; BALANCE_EXHAUSTED means the funding gate is refusing work right now; WELCOME_CREDIT_LOCKED is the same refusal for an organization that never checked a card — adding one unlocks the welcome credit; OWN_KEY_REQUIRED means an organization that runs only on its own keys has none at a provider its work needs.
    - `message` string, required: The whole warning, in plain words.
    - `waiting_work_count` integer, required: How many pieces of work are waiting for funds and would resume after a top-up; zero unless new work is being refused.
  - `auto_top_up` AutoTopUpView, required: Automatic top-ups: when the balance falls to or below a threshold, the card on file is charged a set amount.
    - `enabled` boolean, required: Whether automatic top-ups are on.
    - `threshold_microusd` integer, nullable, required: The balance at or below which a top-up is charged; null when unset. In microusd: millionths of a US dollar (1,000,000 = $1.00).
    - `amount_microusd` integer, nullable, required: How much each automatic top-up adds; null when unset. In microusd: millionths of a US dollar (1,000,000 = $1.00).
    - `card_on_file` boolean, required: Whether a card is saved; automatic top-ups need one.
    - `last_failure` string, nullable, required: Why the last automatic top-up failed, or why automatic top-ups were turned off; cleared by the next successful payment.
  - `welcome_credit` WelcomeCreditView, required: The free welcome credit a new organization unlocks by adding a card.
    - `state` 'locked' | 'unlocked' | 'card_refused' | 'forfeited', required
    - `unlock_amount_microusd` integer, required: How much adding a card unlocks. In microusd: millionths of a US dollar (1,000,000 = $1.00).
    - `granted_microusd` integer, required: How much was granted; zero once forfeited. In microusd: millionths of a US dollar (1,000,000 = $1.00).
    - `refusal` string, nullable, required: Why the last card was not accepted; null otherwise.
    - `work_credit` WorkCreditView, required: The extra welcome credit for a verified company, on top of the card-unlocked credit.
      - `state` 'not_eligible' | 'available' | 'pending' | 'declined' | 'granted', required
      - `upgrade_amount_microusd` integer, required: How much the extra credit adds. In microusd: millionths of a US dollar (1,000,000 = $1.00).
      - `decision_note` string, nullable, required: The reviewer's note on a declined request; null otherwise.
      - `assessment` 'unassessed' | 'pending' | 'qualifies' | 'does_not_qualify', required: The pre-card work-credit verdict on org_billing (the CHECK's mirror): unassessed until an assessment is opened (or when its start failed), pending while it runs, then qualifies or does_not_qualify. The offer reads it; the grant after the card uses a stored qualifies as its evidence instead of re-running the signals.
      - `signal` 'operator_approval' | 'github_organization' | 'google_workspace' | 'aged_domain_with_website', required: What vouched for the company. The automatic signals join this enum as each ships (and temporal/activities/work_credit.py's order); an operator's approval vouches with no subject.
  - `low_balance_alert_threshold_microusd` integer, required: The balance at or below which the low-balance warning shows. In microusd: millionths of a US dollar (1,000,000 = $1.00).
  - `stripe_configured` boolean, required: Whether card payments are available; when false, top-ups cannot be bought but everything else still reads.
  - `stripe_customer_exists` boolean, required: Whether the organization has card history in the billing portal (receipts or a saved card); false until its first card payment or card check.
  - `provider_keys` ProviderKeyView[], required: The organization's own model-provider API keys, at most one per provider; when active, a key pays for that provider's model calls instead of the balance.
    - `provider` 'anthropic' | 'openai' | 'openrouter', required: Whose API a model call dials — the dimension BYOK keys, probes, bounce classification, and platform-key selection all key on. The vocabulary is append-only and each new value arrives with its integration (probe + classifier + key-shape rule + a platform key unless BYOK-only), never ahead of it.
    - `key_prefix` string, required: The key's first 12 characters.
    - `key_last4` string, required: The key's last 4 characters.
    - `state` 'verifying' | 'active' | 'bounced', required: Where an org's BYOK model-provider key stands. Save lands VERIFYING (a probe workflow is deciding whether the key works — deliberately not yet funding calls; the balance pays meanwhile, but never for OpenRouter); a green probe flips ACTIVE (the key now pays for every model call the org causes at its provider); a red probe or a run-time 401/403/credit-exhausted decline flips BOUNCED (work at its provider is refused until the key is replaced — the balance never covers a declined key; the key-declined alert says so).
    - `bounced_reason` string, nullable, required: Why the provider refused the key; null unless bounced.
    - `bounced_at` string, date-time, nullable, required: When the key bounced; null unless bounced.

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `405`: Method not allowed
- `422`: Validation error
- `500`: Internal server error

---

[API](https://skmtc.dev/teaflask/apis/teaflask-api.md) - [All operations](https://skmtc.dev/teaflask/apis/teaflask-api/llms.txt) - [OpenAPI document](https://skmtc.dev/teaflask/apis/teaflask-api/revisions/d23e9286b847?raw)
