# Services : Firebase : Python SDK
[firebase-admin](https://pypi.org/project/firebase-admin/) — [src](https://github.com/firebase/firebase-admin-python/) | [docs](https://firebase.google.com/docs/reference/admin/python) | [firestore](https://cloud.google.com/python/docs/reference/firestore/latest/google.cloud.firestore_v1.client)
```bash
pip install firebase_admin
```
```python
from firebase_admin import auth, credentials, db, firestore, initialize_app
from firebase_admin.firestore import DocumentReference, DocumentSnapshot, FieldFilter
```
## App Initialization
Must call `initialize_app()` before other methods. Returns App instance, though you generally won't need it.
If you don't specify a name, defaults to `"[DEFAULT]"`. If you need multiple apps, specify a separate name for each.
```python
app = initialize_app() # default app, no credentials
app = initialize_app( "foo" ) # "foo" app, no credentials
app = initialize_app( cred=credentials.Certificate( "path/to/cert.json" ) )
app = initialize_app( cred=credentials.Certificate( json.loads( "...cert..." ) ) )
app = initialize_app( options=dict( projectId="..." ) )
```
#### Apps & Creds
```python
app.credential cred.project_id
app.name cred.service_account_email
app.options cred.signer
app.project_id
```
## Auth
#### API
```python
# firebase_admin.auth.<func>
create_user(
uid # User ID to assign to the newly created user (optional).
display_name # The user’s display name (optional).
email # The user’s primary email (optional).
email_verified # A boolean indicating whether or not the user’s primary email is verified (optional).
phone_number # The user’s primary phone number (optional).
photo_url # The user’s photo URL (optional).
password # The user’s raw, unhashed password. (optional).
disabled # A boolean indicating whether or not the user account is disabled (optional).
) -> UserRecord
delete_user( uid )
generate_email_verification_link(
email # The email of the user to be verified.
action_code_settings = None # `ActionCodeSettings` instance (optional).
# Defines whether the link is to be handled by a mobile app
# and the additional state information to be passed in the deep link.
) -> verification link
generate_password_reset_link(
email # The email of the user whose password is to be reset.
action_code_settings = None # `ActionCodeSettings` instance (optional).
# Defines whether the link is to be handled by a mobile app
# and the additional state information to be passed in the deep link.
) -> reset link
get_user( uid ) -> UserRecord # raises auth.UserNotFoundError
get_user_by_email( email ) -> UserRecord # if user not found
list_users(
page_token = None # Indicates starting point (optional). `None` retrieves the first page of users.
max_results = 1000 # 1000 is both the default and the max
) -> ListUsersPage
update_user( uid, **kwargs ) -> UserRecord # same kwargs as create_user()
verify_id_token( id_token ) -> payload # raises InvalidIdTokenError, ExpiredIdTokenError
verify_id_token( id_token, app=None, check_revoked=False, clock_skew_seconds=0 )
```
#### Objects
```python
ListUsersPage
get_next_page()
iterate_all() # returns iter: ExportedUserRecord that starts on this page
has_next_page
next_page_token
users # [ ExportedUserRecord ]
ExportedUserRecord( UserRecord )
password_hash
password_salt
UserRecord( UserInfo )
custom_claims dict | None
disabled bool
display_name str | None
email str | None
email_verified bool
phone_number str | None
photo_url str | None
provider_data [ UserInfo ]
provider_id str
tenant_id str | None
tokens_valid_after_timestamp int
uid str
user_metadata UserMetadata
UserInfo
display_name
email
phone_number
photo_url
provider_id
uid
UserMetadata
creation_timestamp int
last_refresh_timestamp int | None
last_sign_in_timestamp int
```
## Database
#### API
```python
# firebase_admin.db.<func>
reference( path="/", app=None, url=None ) -> Reference
# example
ref = db.reference( "/"[, url="https://DBNAME.firebaseio.com"] )
```
#### Objects
```python
Reference
child( path ) -> Reference
delete()
get( shallow=False ) -> object
listen( callback ) -> ListenerRegistration
order_by_child( path ) -> Query
order_by_key() -> Query
order_by_value() -> Query
push( value="" ) -> Reference
adds child node to object with unique key
set( value )
update( value ) value = map of paths and values
key
parent
path
ListenerRegistration
.close()
Event
.data parsed JSON # new data or None if deleted
.event_type "put" | "patch"
.path # path relative to reference
Query
<chaining methods>
equal_to( value )
start_at( start )
end_at( end )
limit_to_first( limit )
limit_to_last( limit )
<other>
get() -> object
```
## Firestore
### API
```python
client = firestore.client()
```
**Get a Single Document**
```python
doc = client.collection( "cities" ).document( "foo" ).get()
if doc.exists:
print( f"Document data: { doc.to_dict() }" )
else:
print( "No such document!" )
```
**Get Multiple Documents**
```python
for doc in client.collection( "cities" ).where( "capital", "==", True ).stream():
print( f"{ doc.id } => { doc.to_dict() }" )
```
**Get All Documents**
```python
for doc in client.collection( "cities" ).stream():
print( f"{ doc.id } => { doc.to_dict() }" )
```
### Objects
From experience....
```python
collection.document( id ) -> DocumentReference
collection.stream() -> iter: DocumentSnapshot
# DocumentReference and DocumentSnapshot each link to the other - 1:1 relationship
dr.get() -> ds
ds.reference -> dr
# You can call .document() with a non-existant ID and get back a DocumentReference,
# then call .get() on that and get a DocumentSnapshot, with no errors raised.
# With a non-existant DocumentSnapshot:
ds.exists -> False
ds.to_dict() -> None
```
**Query/Collection**
```python
base_query.
BaseQuery( ... )
order_by( "FIELD", direction="ASCENDING" ) -> BaseQuery
recursive() -> BaseQuery
select( ... )
where(
"FIELD", "OP", VALUE
-or-
filter=Fieldfilter( "FIELD", "OP", VALUE )
) -> BaseQuery
query.
Query(
parent <- CollectionReference
projection <- ???
field_filters <- tuple( ??? )
orders <- tuple( ??? )
) < BaseQuery
get -> list
onSnapshot( CALLABLE ) -> Watch
CALLABLE( docs, changes, read_time )
stream -> iter: DocumentSnapshot # stream() preferred over get()
avg/count/sum
base_collection.
BaseCollectionReference
id
parent
document( ... ) -> DocumentReference
select( ... )
where( ... )
order_by( ... )
avg/count/sum
collection.
CollectionReference < BaseCollectionReference[Query]
add( document_data, document_id=None, ... ) -> ( timestamp, DocumentReference )
list_documents -> iter: DocumentReference
```
**Documents**
```python
base_document.
BaseDocumentReference
id
parent
path
collection( ... )
document.
DocumentReference < BaseDocumentReference
collections( ... )
create( ... )
delete( ... )
get() -> DocumentSnapshot
on_snapshot( ... )
set( ... )
update( ... )
base_document.
DocumentSnapshot
create_time
exists -> bool
id
reference -> DocumentReference
to_dict() -> dict
update_time
```
*Add/Create/Update*
```python
coll.add( document_data: dict, document_id=None, retry=..., timeout=None )
dr.create( document_data: dict, retry=..., timeout=None ) # raises Conflict if already exists
dr.set( document_data: dict, merge=False, retry=..., timeout=None )
merge=False replace if exists, create if it doesn't
merge=True merge if exists, create if doesn't
dr.update( field_updates: dict, option=None, retry=..., timeout=None )
By default, verifies document exists before making updates.
field_updates
{ "foo": { "bar": 42 } } # sets document[ "foo" ] to { "bar": 42 }
{ "foo.bar": 42 } # sets document[ "foo" ][ "bar" ] to 42
{ "foo": firestore.DELETE_FIELD } # deletes document[ "foo" ]
{ "foo": firestore.SERVER_TIMESTAMP } # deletes document[ "foo" ]
WARNING: Paths ("foo.bar") can only be used at the top leve.
```