
    ^h!             L       	   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJrJrJ	r	  SSK
JrJrJrJr  SSKrSSKJrJrJrJrJrJrJr  SSKrSSKJr  SSK7  SSKJrJrJrJr  SS	K J!r!  SS
K"J#r#  SSK$J%r%  SSK&J'r'J(r(J)r)  SSK*J+r+  SSK,J-r-J.r.J/r/  S\04S jr1S\2S\\3   S\\4   4S jr5S\2S\6S\\/   4S jr7S\0S\\\3      4S jr8S\2S\6S\04S jr9S\6S\\.   4S jr:S\6S\04S jr;S\\2   S\6S\0S\<4S jr=\" 5       r>\>R                  SS /\" \!5      /\@S!9\%\" \!5      \" SS"S#94S\0S\6S$\\3   4S% jj5       5       rAS\BS&\CS'\CS\C4S( jrDS\E\F\G4   4S) jrH\>R                  S*S /\" \!5      /S+9\%\" \!5      \" SS"S#94S,\S\FS\6S$\\3   4S- jj5       5       rI\>R                  S.S /\" \!5      /S+9\%\" \!5      \" SS"S#94S\JS\6S$\\3   4S/ jj5       5       rK\>R                  S0S /\" \!5      /S1S29S\" \!5      4S\\J   S\64S3 jj5       rL\>R                  S4S /\" \!5      /S+9\R(                  " SS5S69\" \!5      4S7\\3   S\64S8 jj5       rNS/ 0 0 S9SSSSSSSSSSSSSSS0 SSS:SS/ 0 0 SSSSSSS4$S;\OS<   S=\\3   S>\PS?\CS@\CSA\QSB\\Q   SC\\3   SD\\Q   SE\\Q   SF\\Q   SG\\<   SH\\3   SI\\3   S7\\3   S\\3   SJ\\3   SK\\3   SL\\3   SM\\3   SN\\R   SO\\C   SP\\R   SQ\\R   SR\OSS   ST\\C   SU\\3   SV\\P   SW\\C   SX\\C   SY\\C   SZ\\C   S[\\P   S\\\P   S]\\3   S^\\OS_      S`\\<   4JSa jjrS SSb\S\\3   S\\\T   \\U   4   4Sc jjrV\>R                  SdS /\" \!5      /S+9\%S\" \!5      \" SS"S#94S7\3S\\G   S\6S$\\3   S\\@   4
Se jj5       5       rW\>R                  SfS /\" \!5      /S+9\%\" \!5      \" SgShSgSi9\" SjSkSgSlSm9\" SSnS#9\" SSoS#9\" SSpS#94S,\S\6Sq\RSr\RS\\3   SK\\3   SU\\3   4Ss jj5       5       rX\>R                  StS /\" \!5      /S+9\%\" \!5      \" SS"S#94S\YSu\S\6S$\\3   S\\U   4
Sv jj5       5       rZ\>R                  SwS /\" \!5      /S+9\%\" \!5      \" SS"S#94S\YSu\S\6S$\\3   4Sx jj5       5       r[\>R                  SyS /\" \!5      /\\S!9\%\" \!5      4S,\S\64Sz jj5       5       r]S\6S7\\3   S{\US\<4S| jr^S\6S,\S}\\T\3\_4      S\`4S~ jra SSU\\3   S\_S\\3   SS4S jjrbSX\\T   SS4S jrcg)za
KEY MANAGEMENT

All /key management endpoints 

/key/generate
/key/info
/key/update
/key/delete
    N)datetime	timedeltatimezone)ListOptionalTuplecast)	APIRouterDependsHeaderHTTPExceptionQueryRequeststatus)verbose_proxy_logger)*)_cache_key_object_delete_cache_key_objectget_key_objectget_team_object)user_api_key_auth)KeyManagementEventHooks)management_endpoint_wrapper)_hash_token_if_neededduration_in_secondshandle_exception_on_proxy)
get_secret)GenericBudgetInfoPersonalUIKeyGenerationConfigTeamUIKeyGenerationConfigdatac                     U R                   S L$ N)team_idr!   s    u/home/james-whalen/.local/lib/python3.13/site-packages/litellm/proxy/management_endpoints/key_management_endpoints.py_is_team_keyr'   1   s    <<t##    
team_tableuser_idreturnc                 x    Uc  g U R                    H&  nUR                  c  M  UR                  U:X  d  M$  Us  $    g r#   )members_with_rolesr*   )r)   r*   members      r&   _get_user_in_teamr/   5   s;     //>>%&..G*CM 0 r(   user_api_key_dictteam_key_generationc                     Ub  SU;  a  g[        XR                  S9nUc$  [        SSUR                   SU R                   3S9eUR                  US   ;  a  [        SSUR                   S	US    3S9eg)
Nallowed_team_member_rolesT)r)   r*     zUser=z not assigned to team=status_codedetailzTeam member role z" not in allowed_team_member_roles=)r/   r*   r   r$   role)r)   r0   r1   user_in_teams       r&   &_team_key_generation_team_member_checkr:   @   s     	#&.AA$'@'@L ,4455KJL^L^K_`
 	

  34O PP&|'8'8&99[\o  qL  ]M  \N  O
 	
 r(   required_paramsc                 b    Uc  gU R                  SS9nU H  nX2;  d  M
  [        SSU S3S9e   g)NTexclude_unsetr4   zRequired param z not in datar5   )
model_dumpr   )r!   r;   	data_dictparams       r&   $_key_generation_required_param_checkrB   \   sN     d3I !(|<  ! r(   c                     [         R                  b   [         R                  R                  S5      c  g[         R                  S   n[        U UUS9  [	        UUR                  S5      5        g)Nr1   T)r)   r0   r1   r;   )litellmkey_generation_settingsgetr:   rB   )r)   r0   r!   _team_key_generations       r&   _team_key_generation_checkrH   l   so     	''/**../DEM"::;PQ*+0
 )  !23
 r(   personal_key_generationc                     Ub  SU;  a  gU R                   US   ;  a.  [        SS[        R                  S   S    SU R                    3S9eg)Nallowed_user_rolesTr4   zBPersonal key creation has been restricted by admin. Allowed roles=rI   z. Your role=r5   )	user_roler   rD   rE   )r0   rI   s     r&   _personal_key_membership_checkrM      s    
 	 ''>>""*ABV*WWWX_XwXw  yR  YS  Th  Yi  Xj  jv  wH  wR  wR  vS  T
 	

 r(   c                     [         R                  b   [         R                  R                  S5      c  g[         R                  S   n[        U US9  [	        UUR                  S5      5        g)NrI   T)rI   r;   )rD   rE   rF   rM   rB   )r0   r!   _personal_key_generations      r&   _personal_key_generation_checkrP      sl    
 	''/**../HIQ&>>?XY" 8
 ) $$%67
 r(   c                     [         R                  b(  UR                  [        R                  R
                  :X  a  g[        US9nU(       a%  U c  [        SSUR                   3S9e[        U UUS9$ [        XS9$ )zV
Check if admin has restricted key creation to certain roles for teams or individuals
Tr%   r4   z1Unable to find team object in database. Team ID: r5   r)   r0   r!   )r0   r!   )rD   rE   rL   LitellmUserRolesPROXY_ADMINvaluer'   r   r$   rH   rP   )r)   r0   r!   is_team_keys       r&   key_generation_checkrW      s     	''/&&*:*F*F*L*LL D)KJ4<<.Y  *!/
 	
 ./
 	
r(   z/key/generatezkey management)tagsdependenciesresponse_modelzThe litellm-changed-by header enables tracking of actions performed by authorized users on behalf of other users, providing an audit trail for accountability)descriptionlitellm_changed_byc           
      ^	  #     SSK JnJnJnJn  [
        R                  " S5        Ub{  [        R                  " U5      (       a  U" U 5      I Sh  vN nO[        S5      eUR                  SS5      nUR                  SS	5      n	U(       d  [        [        R                  U	S
9eOT[        R                  bC  U R                   c  Sn
O([#        U R                   UUUR$                  S9I Sh  vN n
['        U
UU S9  [        R(                  b  U  H  nUu  pUc2  US;   a,  [+        X[        R(                  R                  US5      5        M<  US:X  a2  U/ :X  a,  [+        X[        R(                  R                  U/ 5      5        Mt  US:X  d  M|  U0 :X  d  M  [+        X[        R(                  R                  U0 5      5        M     [        R,                  b  U  H  nUu  p[/        [        R,                  US5      nUc  M'  Uc  [+        XU5        M8  US;   a  X:  a  [        SSU SU SU 30S
9eMY  US;   d  Ma  [1        US9n[1        US9nUU:  d  M{  [        SSU SU SU 30S
9e   SnUb  U R2                  b  [5        U R2                  U R6                  =(       d    0 S9nUR9                  UR;                  SS95      nUR<                  R>                  RA                  0 UEURB                  =(       d    UURB                  =(       d    US.ES9I Sh  vN n[/        USS5      nU RE                  SSS9nSU;   a  URG                  SS5      US'   Ub  UUS'   SU;   a  URG                  SS5      US '   S!U;   ad  SS"K J$n  USLa,  US!   b&  [        S#[J        RL                  RN                   35      eUS   c  S!US!   0US'   OUS!   US   S!'   URG                  S!5        [Q        UR                  S$S5      US%9I Sh  vN   [S        S,S&S'0UDS(S'0D6I Sh  vN nU R2                  US)'   [        RT                  " [V        RX                  " U UUUS*95        [[        S,0 UD6$  GN GNp GNP Nk NT! [\         a>  n[
        R^                  " S+Ra                  [c        U5      5      5        [e        U5      eSnAff = f7f)-a  
Generate an API key based on the provided data.

Docs: https://docs.litellm.ai/docs/proxy/virtual_keys

Parameters:
- duration: Optional[str] - Specify the length of time the token is valid for. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
- key_alias: Optional[str] - User defined key alias
- key: Optional[str] - User defined key value. If not set, a 16-digit unique sk-key is created for you.
- team_id: Optional[str] - The team id of the key
- user_id: Optional[str] - The user id of the key
- models: Optional[list] - Model_name's a user is allowed to call. (if empty, key is allowed to call all models)
- aliases: Optional[dict] - Any alias mappings, on top of anything in the config.yaml model list. - https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---upgradedowngrade-models
- config: Optional[dict] - any key-specific configs, overrides config in config.yaml
- spend: Optional[int] - Amount spent by key. Default is 0. Will be updated by proxy whenever key is used. https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---tracking-spend
- send_invite_email: Optional[bool] - Whether to send an invite email to the user_id, with the generate key
- max_budget: Optional[float] - Specify max budget for a given key.
- budget_duration: Optional[str] - Budget is reset at the end of specified duration. If not set, budget is never reset. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
- max_parallel_requests: Optional[int] - Rate limit a user based on the number of parallel requests. Raises 429 error, if user's parallel requests > x.
- metadata: Optional[dict] - Metadata for key, store information for key. Example metadata = {"team": "core-infra", "app": "app2", "email": "ishaan@berri.ai" }
- guardrails: Optional[List[str]] - List of active guardrails for the key
- permissions: Optional[dict] - key-specific permissions. Currently just used for turning off pii masking (if connected). Example - {"pii": false}
- model_max_budget: Optional[Dict[str, GenericBudgetInfo]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}}. IF null or {} then no model specific budget.
- model_rpm_limit: Optional[dict] - key-specific model rpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific rpm limit.
- model_tpm_limit: Optional[dict] - key-specific model tpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific tpm limit.
- allowed_cache_controls: Optional[list] - List of allowed cache control values. Example - ["no-cache", "no-store"]. See all values - https://docs.litellm.ai/docs/proxy/caching#turn-on--off-caching-per-request
- blocked: Optional[bool] - Whether the key is blocked.
- rpm_limit: Optional[int] - Specify rpm limit for a given key (Requests per minute)
- tpm_limit: Optional[int] - Specify tpm limit for a given key (Tokens per minute)
- soft_budget: Optional[float] - Specify soft budget for a given key. Will trigger a slack alert when this soft budget is reached.
- tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
- enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)

Examples:

1. Allow users to turn on/off pii masking

```bash
curl --location 'http://0.0.0.0:4000/key/generate'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
        "permissions": {"allow_pii_controls": true}
}'
```

Returns:
- key: (str) The generated api key
- expires: (datetime) Datetime object for when key expires.
- user_id: (str) Unique user id - used for tracking spend across multiple keys for same user id.
r   )litellm_proxy_admin_nameprisma_clientuser_api_key_cacheuser_custom_key_generatezentered /key/generateNz,user_custom_key_generate must be a coroutinedecisionTmessagez(Authentication Failed - Custom Auth Ruler5   )r$   r_   r`   parent_otel_spanrR   )
max_budgetr*   r$   max_parallel_requests	tpm_limit	rpm_limitbudget_durationmodelsmetadata)re   rf   rg   rh   r4   errorz. is over max limit set in config - user_value=z; max_value=)ri   durationrm   )soft_budgetmodel_max_budget)exclude_none)
created_by
updated_byr%   	budget_idr>   rq   re   key_max_budgetri   key_budget_durationrX   )premium_userz)Only premium users can add tags to keys. 	key_alias)ry   r_   request_typekey
table_namero   )r!   responser0   r\   zDlitellm.proxy.proxy_server.generate_key_fn(): Exception occured - {} )3litellm.proxy.proxy_serverr^   r_   r`   ra   r   debugasyncioiscoroutinefunction
ValueErrorrF   r   r   HTTP_403_FORBIDDENrD   rE   r$   r   rd   rW   default_key_generate_paramssetattrupperbound_key_generate_paramsgetattrr   ro   LiteLLM_BudgetTablerp   jsonify_objectjsondblitellm_budgettablecreater*   r?   poprx   CommonProxyErrorsnot_premium_userrU   _enforce_unique_key_aliasgenerate_key_helper_fncreate_taskr   async_key_generated_hookGenerateKeyResponse	Exception	exceptionformatstrr   )r!   r0   r\   r^   r_   r`   ra   resultrb   rc   r)   elemr{   rU   upperbound_valueupperbound_durationuser_duration
_budget_id
budget_row
new_budget_budget	data_jsonrx   r}   es                            r&   generate_key_fnr      sN    Dm+	
 	
 	""#:;#/**+CDD7== !OPPzz*d3Hjj,VWG# & 9 9'   ,,8||#CG
#2 LL"/'9%6%G%G	$ 
 !%"3 ..:!
=S - & 7#F#F#J#J3PT#U H_"Dw'J'J'N'NsTV'WXJ&5B;Dw'J'J'N'NsTV'WX# ( 11=!
#*::C$  $/}+;<  #   %7&303(/C58fglfmmy  {K  zL  2M,&'" !"  8 !$CC2E)93/ -@,OM,/BB&303(/C58fglfmmy  {K  zL  2M,&'" !"? N 
$)9)9)E, ,,!%!6!6!<"J '55T2J *,,@@GG "3";";"W?W"3";";"W?W H  G !+t<JOO$TOJ	 9$*3--d*KI&'!%/Ik"	)/8}}=NPT/UI+, Y?4'If,=,I ?@Q@b@b@h@h?ij  $,)/61B(C	*%09&0A	*%f-MM&!'mmK6'
 	
 	

 0 

"+
8=
 

  	 	#<<!"3#5		
 #.X..u >hF	


$  +&&RYYA	

 (**+s   R-AQ" QBQ" (Q)BQ" Q" A$Q" 76Q" 1Q" C Q" QC&Q" 2Q3Q" Q AQ" R-Q" Q" Q" Q"  Q" "
R*,9R%%R**R-non_default_valuesexisting_metadatac                 d   SU;  a  UR                  5       US'   [        [        US   5      nU R                  SSS9n UR	                  5        H  u  pVU[
        ;   d  M  XcU'   M     X1S'   U$ ! [         a8  n[        R                  " SR                  [        U5      5      5         SnANCSnAff = f)zm
Check LiteLLM_ManagementEndpoint_MetadataFields (proxy/_types.py) for fields that are allowed to be updated
rk   Tru   zLlitellm.proxy.proxy_server.prepare_metadata_fields(): Exception occured - {}N)copyr	   dictr?   items)LiteLLM_ManagementEndpoint_MetadataFieldsr   r   r   r   r   )r!   r   r   casted_metadatar   kvr   s           r&   prepare_metadata_fieldsr     s     ++):)?)?)A:&4!3J!?@OdFI

OO%DA==%&" & &5z"  
&&ZaaA	
 	

s   A- A- -
B/7.B**B/c                     U R                  SS9nUR                  SS 5        0 nUR                  5        H  u  pEU[        ;   a  M  XSU'   M     SU;   aw  UR                  S5      nU(       a_  [	        U[
        5      (       aJ  [        U5      S:  a;  [        US9n[        R                  " [        R                  5      [        US9-   nXS'   S	U;   a{  UR                  S	5      n	U	(       ac  [	        U	[
        5      (       aN  [        U	5      S:  a?  [        U	S9n[        R                  " [        R                  5      [        US9-   n
XS
'   XS	'   UR                  =(       d    0 nSU;   a  [        US   5        [        XUS9nU$ )NTr=   r{   rm   r   rn   secondsexpiresri   budget_reset_atrp   )r!   r   r   )r?   r   r   r   
isinstancer   lenr   r   nowr   utcr   rk   validate_model_max_budgetr   )r!   existing_key_rowr   r   r   r   rm   
duration_sr   ri   key_reset_at	_metadatas               r&   prepare_key_update_datar     sc    ooDo9IMM%!99 !1 "
 ''%))*5Hc22H8I,h?Jll8<<09Z3PPG,3y)..,001BCOS11O$q(,oFJ#<<5	*8UUL4@014C01 ))/RI //!"45G"HI0I r(   z/key/update)rX   rY   requestc                 r  #    SSK JnJnJn   UR	                  SS9nUR                  S5      nUc  [        S5      eUR                  UR                  SSS	9I Sh  vN n	U	c  [        S
SSUR                   30S9e[        XS9n
[        U
R                  SS5      UU	R                  S9I Sh  vN   UR                  U0 U
ESU0ES9I Sh  vN n[!        [#        U5      UUS9I Sh  vN   [$        R&                  " [(        R*                  " UU	UUUS95        Uc  [-        S5      eSU0US   E$  N N Ng NM! [         a  n[.        R0                  " SR3                  [5        U5      5      5        [7        U[        5      (       aV  [9        [;        USS[5        U5       S35      [<        R>                  [;        USS5      [;        US[@        RB                  5      S9e[7        U[8        5      (       a  Ue[9        S[5        U5      -   [<        R>                  [;        USS5      [@        RB                  S9eSnAff = f7f) a	  
Update an existing API key's parameters.

Parameters:
- key: str - The key to update
- key_alias: Optional[str] - User-friendly key alias
- user_id: Optional[str] - User ID associated with key
- team_id: Optional[str] - Team ID associated with key
- models: Optional[list] - Model_name's a user is allowed to call
- tags: Optional[List[str]] - Tags for organizing keys (Enterprise only)
- enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)
- spend: Optional[float] - Amount spent by key
- max_budget: Optional[float] - Max budget for key
- model_max_budget: Optional[Dict[str, GenericBudgetInfo]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}
- budget_duration: Optional[str] - Budget reset period ("30d", "1h", etc.)
- soft_budget: Optional[float] - Soft budget limit (warning vs. hard stop). Will trigger a slack alert when this soft budget is reached.
- max_parallel_requests: Optional[int] - Rate limit for parallel requests
- metadata: Optional[dict] - Metadata for key. Example {"team": "core-infra", "app": "app2"}
- tpm_limit: Optional[int] - Tokens per minute limit
- rpm_limit: Optional[int] - Requests per minute limit
- model_rpm_limit: Optional[dict] - Model-specific RPM limits {"gpt-4": 100, "claude-v1": 200}
- model_tpm_limit: Optional[dict] - Model-specific TPM limits {"gpt-4": 100000, "claude-v1": 200000}
- allowed_cache_controls: Optional[list] - List of allowed cache control values
- duration: Optional[str] - Key validity duration ("30d", "1h", etc.)
- permissions: Optional[dict] - Key-specific permissions
- send_invite_email: Optional[bool] - Send invite email to user_id
- guardrails: Optional[List[str]] - List of active guardrails for the key
- blocked: Optional[bool] - Whether the key is blocked
- aliases: Optional[dict] - Model aliases for the key - [Docs](https://litellm.vercel.app/docs/proxy/virtual_keys#model-aliases)
- config: Optional[dict] - [DEPRECATED PARAM] Key-specific config.

Example:
```bash
curl --location 'http://0.0.0.0:4000/key/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
    "key": "sk-1234",
    "key_alias": "my-key",
    "user_id": "user-1234",
    "team_id": "team-1234",
    "max_budget": 100,
    "metadata": {"any_key": "any-val"},
}'
```
r   )r_   proxy_logging_objr`   Tr=   r{   NNot connected to DB!find_uniquetokenr|   
query_typei  rl   zTeam not found, passed team_id=r5   r!   r   ry   )ry   r_   existing_key_tokenr   )r   r!   hashed_tokenr`   r   )r!   r   r}   r0   r\   z(Failed to update key got response = Noner!   zBlitellm.proxy.proxy_server.update_key_fn(): Exception occured - {}r7   zAuthentication Error()rA   Noner6   rc   typerA   codeAuthentication Error, )"r   r_   r   r`   r?   r   r   get_datar{   r   r$   r   r   rF   r   update_datar   
hash_tokenr   r   r   async_key_updated_hookr   r   r   r   r   r   ProxyExceptionr   ProxyErrorTypes
auth_errorr   HTTP_400_BAD_REQUEST)r   r!   r0   r\   r_   r   r`   r   r{   r   r   r}   r   s                r&   update_key_fnr     so    v J
///=	mmE" 233!.!7!7((u "8 "
 
 ##B4<<.!QR 
 5
 ((,,[$?'/55
 	
 	
 '22@1@7C@ 3 
 
 '#C1/
 	
 	
 	#::!1!"3#5	
 GHHs/hv.//[
	

	
*  
&&PWWA	

 a'' 8/DSVHA-NO$//a&1Qv/J/JK	  >**G,s1v5 ++!Wf-,,	
 	

st   H7AD6 D.AD6 ,D0-D6 
D2D6 &D4'AD6 -H7.D6 0D6 2D6 4D6 6
H4 C/H//H44H7z/key/deletec           
        #     SSK JnJn  Uc  [        S5      eU R                  n[        U5      S:X  a+  [        SU 3[        R                  S[        R                  S9eUR                  n[        R                  " SUR                   35        UR                  b   UR                  [        R                   :X  a  Sn[#        XVS	9I Sh  vN u  pxUc(  [        S
[        R$                  S[        R&                  S9e[        R                  " SUS    35         [        U5      US   :X  d   e U H0  n	UR+                  U	5        [-        U	5      n
UR+                  U
5        M2     [        R                  " SUR.                  R0                   35        [2        R4                  " [6        R8                  " U UUUUS95        SU0$  N! [         a    [)        SSS[        U5       SUS    30S9ef = f! [         a  n[;        U5      eSnAff = f7f)a  
Delete a key from the key management system.

Parameters::
- keys (List[str]): A list of keys or hashed keys to delete. Example {"keys": ["sk-QWrxEynunsNpV1zT48HIrw", "837e17519f44683334df5291321d97b8bf1098cd490e49e215f6fea935aa28be"]}

Returns:
- deleted_keys (List[str]): A list of deleted keys. Example {"deleted_keys": ["sk-QWrxEynunsNpV1zT48HIrw", "837e17519f44683334df5291321d97b8bf1098cd490e49e215f6fea935aa28be"]}

Example:
```bash
curl --location 'http://0.0.0.0:4000/key/delete'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
    "keys": ["sk-QWrxEynunsNpV1zT48HIrw"]
}'
```

Raises:
    HTTPException: If an error occurs during key deletion.
r   )r_   r`   Nr   z"No keys provided, passed in: keys=keysr   zuser_api_key_dict.user_role: tokensr*   zFFailed to delete keys got None response from delete_verification_tokenz/key/delete - deleted_keys=deleted_keysr4   rl   zNot all keys passed in were deleted. This probably means you don't have access to delete all the keys passed in. Keys passed in=z, Deleted keys =r5   z#/keys/delete - cache after delete: )r!   keys_being_deletedr0   r\   r}   )r   r_   r`   r   r   r   r   r   r   r   r   r*   r   r   rL   rS   rT   delete_verification_tokeninternal_server_errorHTTP_500_INTERNAL_SERVER_ERRORr   delete_cacher   in_memory_cache
cache_dictr   r   r   async_key_deleted_hookr   )r!   r0   r\   r_   r`   r   r*   number_deleted_keys_keys_being_deletedr{   r   r   s               r&   delete_key_fnr     s_    DH+P 233yyt9> <TFC$//00	  $++""+,=,G,G+HI	
 ''3!++/?/K/KKG9R:
 4
0 & `$::::	  	"")*=n*M)NO	
	t9 3N CCCC C++C0%c?L++L9	  	""12D2T2T2_2_1`a	
 	#::#6"3#5,	
 %%Y4
   	   `  ad  ei  aj  `k  k{  |O  P^  |_  {`  a 	:  +'**+sU   H
CG- F?	AG- G +BG- >H
?G- )G**G- -
H7HHH
z/v2/key/infoF)rX   rY   include_in_schemac                   #    SSK Jn   Uc  [        S5      eU c  [        [        R
                  SS0S9eUR                  U R                  SS	S
9I Sh  vN nUc  [        [        R                  SS0S9e/ nU H%  n UR                  5       nUR                  U5        M'     U R                  US.$  N]! [         a    UR                  5       n NBf = f! [         a  n[        U5      eSnAff = f7f)a  
Retrieve information about a list of keys.

**New endpoint**. Currently admin only.
Parameters:
    keys: Optional[list] = body parameter representing the key(s) in the request
    user_api_key_dict: UserAPIKeyAuth = Dependency representing the user's API key
Returns:
    Dict containing the key and its associated information

Example Curl:
```
curl -X GET "http://0.0.0.0:4000/key/info"     -H "Authorization: Bearer sk-1234"     -d {"keys": ["sk-1", "sk-2", "sk-3"]}
```
r   r_   NDatabase not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keysrc   z%Malformed request. No keys passed in.r5   r{   find_allr   zNo keys foundr{   info)r   r_   r   r   r   HTTP_422_UNPROCESSABLE_ENTITYr   r   HTTP_404_NOT_FOUNDr?   r   appendr   )r!   r0   r_   key_infofiltered_key_infor   r   s          r&   info_key_fn_v2r     s    6 9+  T  <"@@!#JK 
 '//))* 0 
 
 "55!?3  ALLN $$Q'  yy*;<<!
  FFH  +'**+s_   C0A	C B1(C =B3#C 0C01C 3CC CC 
C-C((C--C0z	/key/infozKey in the request parameters)defaultr[   r{   c                 x  #    SSK Jn   Uc  [        S5      eU =(       d    UR                  n U nU b	  [	        U S9nUR
                  R                  R                  SU0SS0S	9I Sh  vN nUc(  [        S
[        R                  S[        R                  S9e[        UU US9SLa1  [        [        R                  SR!                  UR"                  5      S9e UR%                  5       nUR)                  S5        XS.$  N! [         a    UR'                  5       n N3f = f! [         a  n[+        U5      eSnAff = f7f)aV  
Retrieve information about a key.
Parameters:
    key: Optional[str] = Query parameter representing the key in the request
    user_api_key_dict: UserAPIKeyAuth = Dependency representing the user's API key
Returns:
    Dict containing the key and its associated information

Example Curl:
```
curl -X GET "http://0.0.0.0:4000/key/info?key=sk-02Wr4IAlN3NvPXvL5JVvDA" -H "Authorization: Bearer sk-1234"
```

Example Curl - if no key is passed, it will use the Key Passed in Authorization Header
```
curl -X GET "http://0.0.0.0:4000/key/info" -H "Authorization: Bearer sk-02Wr4IAlN3NvPXvL5JVvDA"
```
r   r   Nr   r   r   litellm_budget_tableT)whereincludezKey not found in databaser{   r   r0   r{   r   z;You are not allowed to access this key's info. Your role={}r5   r   )r   r_   r   api_keyr   r   litellm_verificationtokenr   r   r   not_found_errorr   r   _can_user_query_key_infor   r   r   rL   r?   r   r   r   )r{   r0   r_   
hashed_keyr   r   s         r&   info_key_fnr  J  sf    : 9.+  T 
 .&..$'
?.S9J&))CCOOJ'+T2 P 
 
  3$44..	  %"3!
   "55T[[%// 	'**,H 	W--C
:  	'}}H	'
  +'**+s`   D:AD &C;'A.D C= &D :D:;D =DD DD 
D7'D22D77D:g        insert_datarz   )userr{   rm   rj   aliasesconfigspendrv   rw   rt   ro   re   blockedri   r   
user_aliasr$   
user_emailrL   rf   rk   rg   rh   r   )r  r   update_key_valuesry   allowed_cache_controlspermissionsrp   model_rpm_limitmodel_tpm_limit
guardrailsteamsorganization_idr|   )r{   r  send_invite_emailc%                 
  #    SSK Jn%Jn&Jn'  U'c  [	        S5      eUc  Ub  UnOS[
        R                  " S5       3nUc  S n(O7[        US9n)[        R                  " [        R                  5      [        U)S9-   n(Uc  S n*O7[        US9n)[        R                  " [        R                  5      [        U)S9-   n*Uc  S n+O7[        US9n)[        R                  " [        R                  5      [        U)S9-   n+[        R                  " U5      n,[        R                  " U5      n-[        R                  " U5      n.Ub  U=(       d    0 nUUS'   Ub  U=(       d    0 nUUS	'   U b  U=(       d    0 nU US
'   [        R                  " U5      n/[        U5        [        R                  " U5      n0UnUnUnUn 0 SU
_SU_SU_SU_SU_SU"_SU_SU_SU_SU/_SU_SU_SU_SU_SU+_SU_n1U!b  U!U1S'   0 SU_SU_SU(_SU_SU,_S U-_SU_SU_SU_SU_SU_SU/_SU_SU_SU_SU*_SU_U.U0UUS!.En2[!        S"S#5      S$L a  OS%US&S   3U2S''   ["        R$                  " U25      n3['        U3S   [(        5      (       a  [        R*                  " U3S   5      U3S'   ['        U3S    [(        5      (       a  [        R*                  " U3S    5      U3S '   ['        U3S   [(        5      (       a  [        R*                  " U3S   5      U3S'   ['        U3S(   [(        5      (       a5  S)U3S(   ;   a  U&S$La  [-        S*5      e[        R*                  " U3S(   5      U3S('   ['        U3S+   [(        5      (       a  [        R*                  " U3S+   5      U3S+'   U3R/                  SS 5      b.  ['        U3S   [        5      (       a  U3S   R1                  5       U3S'   U'b  U#b  U#S,:X  a  US-:X  aa  U'R3                  U1S,S.9I S h  vN n4U4c  [	        S/5      e[5        U4R6                  5      S:  a!  [5        U2S   5      S:X  a  U4R6                  U2S'   OUS0:X  a  U'R9                  U1S,US19I S h  vN n4UU%:X  d	  U#b  U#S,:X  a  U1$ [:        R<                  " S2U25        U'R3                  U2S3S.9I S h  vN n5[?        U5SS 5      U2S4'   UU2S9'   U S,:X  a  U2RO                  U15        U2$  N Nt N6! [         a  n6[:        R@                  " S5RC                  [)        U65      5      5        [:        R<                  " [D        RF                  " 5       5        ['        U6[H        5      (       a  U6e[I        [J        RL                  S6S70S89eS n6A6ff = f7f):Nr   )litellm_proxy_budget_namerx   r_   z]Connect Proxy to database to generate keys - https://docs.litellm.ai/docs/proxy/virtual_keys sk-   rn   r   r  r  r  re   r  r*   r  r$   r  rL   r
  rj   rk   rf   rg   rh   ri   r   r  r  r   ry   r   r  r	  )r  rp   rt   r  DISABLE_KEY_NAMEFTsk-...key_namer  get_spend_routeszJget_spend_routes permission is only available for LiteLLM Enterprise usersrp   r  r  )r!   r|   zFailed to create userr   )r!   r|   r  zprisma_client: Creating Key= %sr{   token_idzKlitellm.proxy.proxy_server.generate_key_helper_fn(): Exception occured - {}rl   zInternal Server Error.r5   rt   )(r   r  rx   r_   r   secretstoken_urlsafer   r   r   r   r   r   r   dumpsr   r   r   deepcopyr   r   loadsr   rF   	isoformatr  r   rj   r   r   r   r   rl   r   	traceback
format_excr   r   r   update)7rz   rm   rj   r  r	  r
  rv   rw   rt   ro   re   r  ri   r   r{   r*   r  r$   r  rL   rf   rk   rg   rh   r   r  ry   r  r  rp   r  r  r  r  r  r|   r  r  rx   r_   r   r   r   reset_ataliases_jsonconfig_jsonpermissions_jsonmetadata_jsonmodel_max_budget_json	user_datakey_datasaved_tokenuser_rowcreate_key_responser   s7                                                          r&   r   r     s    Z  k
 	
 }?E'//345E((;
,,x||,y/LL"(2EF
||HLL1Ij4QQ(/B
<<-	*0MM::g&L**V$Kzz+. ">r&5"#">r&5"#>r!+JJx(M./ JJ'78III3}

*
*
 w
 *	

 w
 
 
 U
 f
 
 $%:
 
 
 
 x
  %&<!
	$ !&Ig
U

 w
 f	

 |
 k
 U
 .
 w
 w
 $%:
 
 
 
 2
  |!
" %&<#
$ , 5"+
2 )51T9%+E"#J<#8HZ mmH-k),c22%)ZZI0F%GK	"k(+S11$(JJ{8/D$EK!k*-s33&*jjZ1H&IK
#k-0#66"k-&@@ , `  *.K4N)OK&k"45s;;.2jj.//K*+ ??9d+7J	"H=
 =
 &1%;%E%E%GK	"$"jF&: .%2%>%>&6 &? &  H  ''(?@@8??+a/C8J4Kq4P-5__*=0%2%>%>&#)*; &? &  H
 33&:+?
 !  !&&'H(S(5(A(A% )B ) # $++>#NHZ   &H[v	"Oc  #  
""Y``A	

 	""9#7#7#9:a''G==56
 	

so   F,U/H*R: R4A'R: R6R: U*R: R8R: U4R: 6R: 8R: :
UBUUUr   c                   #    SSK JnJn   U(       a  U  Vs/ s H  n[        US9PM     n nUR                  R
                  R                  SSU 00S9I Sh  vN nX:X  a  UR                  U S9I Sh  vN nOlUR                  XS	9I Sh  vN nUc  [        S
5      eUR                  SS5      nU[        U 5      :w  a  [        S[        U5      -   5      e Xe4$ [        S5      e Xe4$ s  snf  N N| Nf! [         a^  n[        R                  " SR                  [        U5      5      5        [        R                  " [         R"                  " 5       5        UeSnAff = f7f)a:  
Helper that deletes the list of tokens from the database

Args:
    tokens: List of tokens to delete
    user_id: Optional user_id to filter by

Returns:
    Tuple[Optional[Dict], List[LiteLLM_VerificationToken]]:
        Optional[Dict]:
            - Number of deleted tokens
        List[LiteLLM_VerificationToken]:
            - List of keys being deleted, this contains information about the key_alias, token, and user_id being deleted,
            this is passed down to the KeyManagementEventHooks to delete the keys from the secret manager and handle audit logs
r   )r^   r_   r   r   inr   N)r   r   z>Failed to delete tokens got response None when deleting tokensr   zOFailed to delete all tokens. Tried to delete tokens that don't belong to user: 'DB not connected. prisma_client is NonezNlitellm.proxy.proxy_server.delete_verification_token(): Exception occured - {})r   r^   r_   r   r   r  	find_manydelete_datar   rF   r   r   r   rl   r   r   r'  r(  )	r   r*   r^   r_   r{   r   deleted_tokens_num_deleted_tokensr   s	            r&   r   r     s    $ S%BHI&3+#6&FI#&&@@JJ"T6N3 K     2'4'@'@'@'O!O (5'@'@! (A ( " ")#X  '5&8&8&K#&#f+5#ig,'  6 .. EFF# 4 ..I J "P"  ""\ccA	

 	""9#7#7#9:sv   	EC3 C(,C3 C-C3 2C/3C3 
C1A
C3 EC3 $E(C3 /C3 1C3 3
E=AEEEz/key/{key:path}/regeneratec                   #     SSK JnJnJnJnJn  USLa&  [        S[        R                  R                   35      eUc  [        [        R                  SS0S9eS	U ;  a  U n	OU" U 5      n	UR                  R                  R                  S
U	0S9I Sh  vN n
U
c  [        [        R                   SSU  S30S9e["        R$                  " SU
5        S[&        R(                  " S5       3nU" U5      nSUSS  3nUUS.n0 nUb   [+        XS9n["        R$                  " SU5        UR-                  U5        UR/                  US9nUR                  R                  R-                  S
U	0US9I Sh  vN n0 nUb  [1        U5      nUUS'   UR3                  S
5        U (       a  [5        U" U 5      UUS9I Sh  vN   U	(       a  [5        U" U 5      UUS9I Sh  vN   [7        S0 UD6$  GNO Nx N4 N! [8         a  n[;        U5      eSnAff = f7f)a2	  
Regenerate an existing API key while optionally updating its parameters.

Parameters:
- key: str (path parameter) - The key to regenerate
- data: Optional[RegenerateKeyRequest] - Request body containing optional parameters to update
    - key_alias: Optional[str] - User-friendly key alias
    - user_id: Optional[str] - User ID associated with key
    - team_id: Optional[str] - Team ID associated with key
    - models: Optional[list] - Model_name's a user is allowed to call
    - tags: Optional[List[str]] - Tags for organizing keys (Enterprise only)
    - spend: Optional[float] - Amount spent by key
    - max_budget: Optional[float] - Max budget for key
    - model_max_budget: Optional[Dict[str, GenericBudgetInfo]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}
    - budget_duration: Optional[str] - Budget reset period ("30d", "1h", etc.)
    - soft_budget: Optional[float] - Soft budget limit (warning vs. hard stop). Will trigger a slack alert when this soft budget is reached.
    - max_parallel_requests: Optional[int] - Rate limit for parallel requests
    - metadata: Optional[dict] - Metadata for key. Example {"team": "core-infra", "app": "app2"}
    - tpm_limit: Optional[int] - Tokens per minute limit
    - rpm_limit: Optional[int] - Requests per minute limit
    - model_rpm_limit: Optional[dict] - Model-specific RPM limits {"gpt-4": 100, "claude-v1": 200}
    - model_tpm_limit: Optional[dict] - Model-specific TPM limits {"gpt-4": 100000, "claude-v1": 200000}
    - allowed_cache_controls: Optional[list] - List of allowed cache control values
    - duration: Optional[str] - Key validity duration ("30d", "1h", etc.)
    - permissions: Optional[dict] - Key-specific permissions
    - guardrails: Optional[List[str]] - List of active guardrails for the key
    - blocked: Optional[bool] - Whether the key is blocked


Returns:
- GenerateKeyResponse containing the new key and its updated parameters

Example:
```bash
curl --location --request POST 'http://localhost:4000/key/sk-1234/regenerate'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data-raw '{
    "max_budget": 100,
    "metadata": {"team": "core-infra"},
    "models": ["gpt-4", "gpt-3.5-turbo"]
}'
```

Note: This is an Enterprise feature. It requires a premium license to use.
r   )r   rx   r_   r   r`   Tz4Regenerating Virtual Keys is an Enterprise feature, Nrl   r8  r5   skr   r7  Key z not found.zkey_in_db: %sr  r  r  r  )r   r  r   znon_default_values: %sr%   r   r!   r{   r   r~   )r   r   rx   r_   r   r`   r   r   r   rU   r   r   r   r   r  r   r   r   r   r!  r"  r   r)  r   r   r   r   r   r   r   )r{   r!   r0   r\   r   rx   r_   r   r`   hashed_api_key
_key_in_db	new_tokennew_token_hashnew_token_key_namer   r   updated_tokenupdated_token_dictr   s                      r&   regenerate_key_fnrH    s    zd+	
 	
 t#FGXGiGiGoGoFpq   "AA!JK 
 s? N'_N(++EEQQN+ R 
 

 "554uK!89 
 	""?J?'//345	#I.%in%56 $*

  !8" !&&'?AST-.#222D+..HHOON+ P 
 

  $!%m!4$-5!w' *'_#5"3   *'_#5"3   # 
 
 	
y
@
  +'**+ss   HBG+ G"CG+ ,G%-AG+ 2G'3G+ G)G+ !H"G+ %G+ 'G+ )G+ +
H5H  HHz	/key/list   zPage number)r[   ge
   z	Page sized   )r[   rJ  lezFilter keys by user IDzFilter keys by team IDzFilter keys by key aliaspagesizec                 @  #     SS K nSSKJn  UR                  S5        Uc  UR	                  S5        [        S5      e1 Skn	[        U R                  R                  5       5      U	-
  n
U
(       a[  [        SSR                  U
5       SSR                  U	5       3[        R                  SR                  U
5      [        R                  S	9e0 nU(       a  [        U[         5      (       a  XKS
'   U(       a  [        U[         5      (       a  X[S'   U(       a  [        U[         5      (       a  XkS'   UR                  SU 35        US-
  U-  nUR                  SU SU 35        UR"                  R$                  R'                  UUUS9I S h  vN nUR                  S[)        U5       S35        UR"                  R$                  R+                  US9I S h  vN nUR                  SU 35        U* U-  * n/ nU H5  nUR-                  5       nUR/                  S5      nUR1                  U5        M7     UUUUS.nUR                  S5        U$  N Nx! [
         a  n[        U[2        5      (       aV  [        [5        USS[!        U5       S35      [        R6                  [5        USS5      [5        US[        R8                  5      S	9e[        U[        5      (       a  Ue[        S[!        U5      -   [        R6                  [5        USS5      [        R8                  S	9eS nAff = f7f) Nr   r   zEntering list_keys functionzDatabase not connected>   rN  rO  r$   r*   ry   zUnsupported parameter(s): z, z. Supported parameters: r   r*   r$   ry   zFilter conditions: rI  zPagination: skip=z, take=)r   skiptakezFetched z keysr7  zTotal count of keys: r   )r   total_countcurrent_pagetotal_pageszSuccessfully prepared responser7   zerror(r   rA   r   r6   r   )loggingr   r_   r   rl   r   setquery_paramsr   r   joinr   bad_request_errorr   r   r   r   r   r  r9  r   countr   rF   r   r   r   r   r   )r   r0   rN  rO  r*   r$   ry   rV  r_   supported_paramsunsupported_paramsr   rQ  r   rS  rU  key_listr{   key_dict_tokenr}   r   s                         r&   	list_keysra  j  s    Z
<34 MM23455 O !5!5!:!:!<=@PP 4TYY?Q5R4SSklplulu  wG  mH  lI  J$66ii 2300	  z'3//&)z'3//&)Is33!*++E734 qD )$wtf=> #%%??II J 
 
 	T512 *,,FFLL M 
 
 	-k];< %,- CxxzH\\'*FOOF#  & &	
 	67E

6  
a'' 8vc!fXQ-?@$::a&1Qv/T/TU	  >**G,s1v5 66!Wf-66	
 	

sP   LFI IAI I	A5I LI 	I 
LCLLLz
/key/blockhttp_requestc                 *  #    SSK JnJnJnJnJnJn	  Uc2  [        SR                  [        R                  R                  5      5      eU R                  R                  S5      (       a  U" U R                  S9n
OU R                  n
[        R                  SL Ga  UR                   R"                  R%                  SU
0S	9I Sh  vN nUc6  ['        S
U R                   S3[(        R*                  S[,        R.                  S9e[0        R2                  " U" [5        [7        [8        R:                  " 5       5      [<        R>                  " [@        RB                  5      U=(       d    URD                  =(       d    UURF                  [H        RJ                  U
SSURM                  5       S9	S95        UR                   R"                  RO                  SU
0SS0S9I Sh  vN n[Q        U
UU	SUS9I Sh  vN nSUl)        [U        U
UU	US9I Sh  vN   U$  GNI N9 N& N7f)a  
Block an Virtual key from making any requests.

Parameters:
- key: str - The key to block. Can be either the unhashed key (sk-...) or the hashed key value

 Example:
```bash
curl --location 'http://0.0.0.0:4000/key/block'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
    "key": "sk-Fn8Ej39NxjAXrvpUGKghGw"
}'
```

Note: This is an admin-only endpoint. Only proxy admins can block keys.
r   create_audit_log_for_updater   r^   r_   r   r`   N{}r  r   Tr   r7  r?  
 not foundr{   r   r  	id
updated_at
changed_bychanged_by_api_keyr|   	object_idactionupdated_valuesbefore_valuerequest_datar@  r   r_   r`   rd   r   r   user_api_key_objr`   r   +r   re  r   r^   r_   r   r`   r   r   r   db_not_connected_errorrU   r{   
startswithrD   store_audit_logsr   r  r   r   r   rZ  r   r   r   r   LiteLLM_AuditLogsr   uuiduuid4r   r   r   r   r*   r   LitellmTableNamesKEY_TABLE_NAMEmodel_dump_jsonr)  r   r  r   r!   rb  r0   r\   re  r   r^   r_   r   r`   r   record
key_objects                r&   	block_keyr    s    >  $5$L$L$R$RSTTxx5!!!1xx4'$''AAMML) N 
 
 > txxj
3$66..	  	'.4::<('||HLL91  0(00 0/'8'@'@0??*$#'!'!7!7!9	
$ !##==DD%Y,= E  F &!#-+ J J !#-+	   Mm
8I   B?HH
DHHH(H)HHHHHHz/key/unblockc                 *  #    SSK JnJnJnJnJnJn	  Uc2  [        SR                  [        R                  R                  5      5      eU R                  R                  S5      (       a  U" U R                  S9n
OU R                  n
[        R                  SL Ga  UR                   R"                  R%                  SU
0S	9I Sh  vN nUc6  ['        S
U R                   S3[(        R*                  S[,        R.                  S9e[0        R2                  " U" [5        [7        [8        R:                  " 5       5      [<        R>                  " [@        RB                  5      U=(       d    URD                  =(       d    UURF                  [H        RJ                  U
SSURM                  5       S9	S95        UR                   R"                  RO                  SU
0SS0S9I Sh  vN n[Q        U
UU	SUS9I Sh  vN nSUl)        [U        U
UU	US9I Sh  vN   U$  GNI N9 N& N7f)a  
Unblock a Virtual key to allow it to make requests again.

Parameters:
- key: str - The key to unblock. Can be either the unhashed key (sk-...) or the hashed key value

Example:
```bash
curl --location 'http://0.0.0.0:4000/key/unblock'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
    "key": "sk-Fn8Ej39NxjAXrvpUGKghGw"
}'
```

Note: This is an admin-only endpoint. Only proxy admins can unblock keys.
r   rd  Nrf  r  r   Tr   r7  r?  rg  r{   r   r  rh  rq  Fr@  rs  rt  rv  r  s                r&   unblock_keyr  A  s    >  $5$L$L$R$RSTTxx5!!!1xx4'$''AAMML) N 
 
 > txxj
3$66..	  	'.4::<('||HLL91  0(00 0/'8'@'@0??*$#'!'!7!7!9	
$ !##==DD%Y,> E  F &!#-+ J J !#-+	   Mm
8r  z/key/healthc           
      v  #     UR                   n[        SSS9nU(       a:  SU;   a4  [        UU US   S9I Sh  vN nXCS'   UR                  S5      S:X  a  SUS	'   [        S0 UD6$  N-! [         aD  n[        S
[        U5       3[        R                  [        USS5      [        R                  S9eSnAff = f7f)a  
Check the health of the key

Checks:
- If key based logging is configured correctly - sends a test log

Usage 

Pass the key in the request header

```bash
curl -X POST "http://localhost:4000/key/health"      -H "Authorization: Bearer sk-1234"      -H "Content-Type: application/json"
```

Response when logging callbacks are setup correctly:

```json
{
  "key": "healthy",
  "logging_callbacks": {
    "callbacks": [
      "gcs_bucket"
    ],
    "status": "healthy",
    "details": "No logger exceptions triggered, system is healthy. Manually check if logs were sent to ['gcs_bucket']"
  }
}
```


Response when logging callbacks are not setup correctly:
```json
{
  "key": "unhealthy",
  "logging_callbacks": {
    "callbacks": [
      "gcs_bucket"
    ],
    "status": "unhealthy",
    "details": "Logger exceptions triggered, system is unhealthy: Failed to load vertex credentials. Check to see if credentials containing partial/invalid information."
  }
}
```
healthyN)r{   logging_callbacksrV  )r0   r   key_loggingr  r   	unhealthyr{   zKey health check failed: rA   r   r   r~   )rk   KeyHealthResponsetest_key_loggingrF   r   r   r   r   r   r   r   r   )r   r0   key_metadatahealth_statuslogging_statusesr   s         r&   
key_healthr    s     r
(11+<",
 I5%5"3(3&  
 2B-.  ##H-<'2e$ 1=11   
/Ax8 66!Wf-66	
 	

s8   B94A( A&,A( %B9&A( (
B62?B11B66B9r   c                     U R                   [        R                  R                  :X  d(  U R                   [        R                  R                  :X  a  gU R
                  U:X  a  gUR                  U R                  :X  a  gg)z:
Helper to check if the user has access to the key's info
TF)rL   rS   rT   rU   PROXY_ADMIN_VIEW_ONLYr   r*   r   s      r&   r  r    si     	##'7'C'C'I'II&&*:*P*P*V*VV		"	"c	)			.66	6r(   r  c           	        #    SSK nSSKJn  SSKJn  SSKJnJn  / nU H4  n	U	R                  S5      b  UR                  U	S   5        M+  [        S5      e   U" 5       n
UR                  U
5      nUR                  UR                  5        UR                  5       nUR                  U5         SS	S
S./SS.nU" UU UUUS9I Sh  vN n[         R"                  " S0 UD6I Sh  vN   [*        R,                  " S5      I Sh  vN   U
R/                  5       nUR1                  U5        U(       a  ['        USSU 3S9$ ['        USSU S3S9$  N Ni! [$         a!  n['        USS[)        U5       3S9s SnA$ SnAff = f N{7f)a  
Test the key-based logging

- Test that key logging is correctly formatted and all args are passed correctly
- Make a mock completion call -> user can check if it's correctly logged
- Check if any logger.exceptions were triggered -> if they were then returns it to the user client side
r   N)StringIO)add_litellm_data_to_request)general_settingsproxy_configcallback_namez(callback_name is required in key_loggingzopenai/litellm-key-health-testr  zQHello, this is a test from litellm /key/health. No LLM API call was made for this)r8   contentztest response)modelmessagesmock_response)r!   r0   r  r  r   r  zLogging test failed: )	callbacksr   details   z2Logger exceptions triggered, system is unhealthy: r  zWNo logger exceptions triggered, system is healthy. Manually check if logs were sent to  r~   )rV  ior  $litellm.proxy.litellm_pre_call_utilsr  r   r  r  rF   r   r   StreamHandlersetLevelERROR	getLogger
addHandlerrD   acompletionr   LoggingCallbackStatusr   r   sleepgetvalueremoveHandler)r0   r   r  rV  r  r  r  r  r  callbacklog_capture_stringchloggerr!   r   log_contentss                   r&   r  r    s     PI#%<<(4$$Xo%>?GHH	   "			1	2BKK F
b
5 #r -	
 1/%-
 
 !! 

 	
 	
 --	  
 &..0L
$'HW
 	
 %'mn  nA  AB  C
 	
?
	
  
$'+CF84
 	

sg   B)E=,E E	E !E"E &E=?E; A	E=	E E 
E8E3-E8.E=3E88E=r_   r   c                    #    U bq  Ubm  SU 0nU(       a  SU0US'   UR                   R                  R                  US9I Sh  vN nUb,  [        SU  S3[        R
                  S[        R                  S9eggg N67f)	a  
Helper to enforce unique key aliases across all keys.

Args:
    key_alias (Optional[str]): The key alias to check
    prisma_client (Any): Prisma client instance
    existing_key_token (Optional[str]): ID of existing key being updated, to exclude from uniqueness check
        (The Admin UI passes key_alias, in all Edit key requests. So we need to be sure that if we find a key with the same alias, it's not the same key we're updating)

Raises:
    ProxyException: If key alias already exists on a different key
Nry   r   NOTr7  zKey with alias 'zB' already exists. Unique key aliases across all keys are required.r   )r   r  
find_firstr   r   rZ  r   r   )ry   r_   r   where_clauseexisting_keys        r&   r   r   k  s     " !:(3Y'?#*,>"?L*--GGRR S 
 
 # *9+5wx$66!00	  $ ";
s   ?A:A87A:c                 .    U c  g[        U 5      S:X  a  gU bS  U R                  5        H>  u  p[        U[        5      (       d   eSU;   a  [	        US   5      US'   [        S0 UD6  M@     gg! [         a  n[        S[        U5       S35      eSnAff = f)z
Validate the model_max_budget is GenericBudgetConfigType

Raises:
    Exception: If model_max_budget is not a valid GenericBudgetConfigType
Nr   budget_limitzInvalid model_max_budget: zM. Example of valid model_max_budget: https://docs.litellm.ai/docs/proxy/usersr~   )r   r   r   r   floatr   r   r   )rp   _model_budget_infor   s       r&   r   r     s    
# A%'(8(>(>(@$!&#.... "\138n9U3VL0!1L1 )A (  
(Q0}~
 	

s"   A- A- AA- -
B7BBr#   )d__doc__r   r   r   r!  r'  r{  r   r   r   typingr   r   r   r	   fastapir
   r   r   r   r   r   r   rD   litellm._loggingr   litellm.proxy._typeslitellm.proxy.auth.auth_checksr   r   r   r   $litellm.proxy.auth.user_api_key_authr   .litellm.proxy.hooks.key_management_event_hooksr   &litellm.proxy.management_helpers.utilsr   litellm.proxy.utilsr   r   r   litellm.secret_managers.mainr   litellm.types.utilsr   r   r    GenerateKeyRequestr'   LiteLLM_TeamTableCachedObjr   Memberr/   UserAPIKeyAuthr:   rB   rH   rM   rP   boolrW   routerpostr   r   	BaseModelr   r   UnionUpdateKeyRequestRegenerateKeyRequestr   r   
KeyRequestr   r   rF   r  Literallistr  intr   DictLiteLLM_VerificationTokenr   rH  ra  BlockKeyRequestr  r  r  r  r  Anyr  r  r   r   r~   r(   r&   <module>r     s
  	       2 2 . .  U U U  1 "  C R N 
 4 $) $*5=c]f*% "";<8
/7S	/B *% 4%%&CD&%-?2
34
%
 
 
	
D 
 
	+,-&	    )00A(B(. t)h+
h+%h+ !h+ h+V
)-BF	:(
 "66
7(V )*'BS:T9U    )00A(B(. t)	G
G

G
 &G
 !	G
 G
T )*'BS:T9U    )00A(B(. t)f+
f+%f+ !f+ f+R 
	+,-	   "&(/0A(B5+
:
5+%5+5+p '(@Q8R7S   !"A )00A(B	J+	#J+ &	J+J+b #&*)-!% 	"&"%) 	! $! $#+/!##8E(,#-/"$')&*&*!% %)37(,Wll sm	l
 l l l l UOl "#l l l l  d^!l" c]#l$ C=%l& 

'l, c]-l. /l0 c]1l2 3l4 }5l6 $C=7l8 tn9l: };l< }=l> 45?l@  ~AlB }ClD %TNElF $GlH tnIlJ d^KlL d^MlN OlP D>QlR c]SlT /0UlV  ~Wl` ,0:/:/#C=:/
8D>4 9::;:/z  
	+,-  
  ,0(/0A(B(. t)	[+	[+
'
([+ &[+ !	[+ !"[+ [+| 
	+,-  
  )00A(Ba]q9bkaC@"45MN"45MN$T7QRc
c
%c
 c
 	c

 c]c
 c]c
 }c
 c
L ()AR9S8T    )00A(B(. t)	d
dd &d !	d '(d dN *+7CT;U:V    )00A(B(. t)	d
dd &d !	d dN 
	+,-$	    )00A(BP
P
%P
 P
f%	# ( 
	*M
%M
M
 d38n%M
 	M
f )- }   !  
	 F
 
4 
r(   