Python SDK
Official Python client for SigninID. Supports both sync and async operations.
Installation
pip install signinidRequires Python 3.10 or later.
Basic Usage
from signinid import SigninID
# Set SIGNINID_SECRET_KEY environment variable
client = SigninID()
# Wait for a new verification email to arrive
email = client.inbox.wait_for_new(to="user@test.com")
# Extract the OTP
if email:
print(f"Verification code: {email.detected_otp}")Async Support
import asyncio
from signinid import AsyncSigninID
async def main():
async with AsyncSigninID(secret_key="sk_live_...") as client:
email = await client.inbox.wait_for_new(to="user@test.com")
if email:
print(f"OTP: {email.detected_otp}")
asyncio.run(main())Configuration
The client reads from SIGNINID_SECRET_KEY environment variable by default. You can also pass the secret key directly:
# Using environment variable (recommended)
client = SigninID()
# Or pass secret key directly
client = SigninID(secret_key="sk_live_...")Client Options
| Option | Type | Default | Description |
|---|---|---|---|
secret_key | str | None | env var | Secret key (falls back to SIGNINID_SECRET_KEY) |
timeout | int | 30000 | Request timeout in milliseconds |
Inbox Methods
client.inbox.wait_for_new(**params)
Wait for a new email to arrive. Polls the inbox until a new email arrives or timeout is reached. This is the recommended method for testing signup/login flows.
Example
email = client.inbox.wait_for_new(to="user@test.com")
if email:
print(f"OTP: {email.detected_otp}")Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
to | str | None | - | Filter by recipient (partial match) |
timeout | int | 30 | Maximum wait time in seconds |
Response Type: InboxEmail | None
Returns None if timeout reached.
| Field | Type | Description |
|---|---|---|
email_id | str | Unique identifier |
detected_otp | str | None | Auto-extracted verification code |
html_body | str | None | HTML content |
text_body | str | None | Plain text content |
from_address | str | Sender email address |
from_name | str | None | Sender display name |
to_addresses | tuple[str, ...] | Recipient addresses |
cc_addresses | tuple[str, ...] | None | CC addresses |
subject | str | None | Email subject |
received_at | datetime | When email was received |
message_id | str | None | SMTP Message-ID header |
has_attachments | bool | Has attachments |
attachment_count | int | Number of attachments |
spam_score | float | None | Spam score |
spam_verdict | PASS | FAIL | GRAY | None | Spam classification |
spam_rules | SpamRules | None | Detailed spam rules |
virus_verdict | SecurityVerdict | Virus scan result |
spf_verdict | SecurityVerdict | SPF authentication |
dkim_verdict | SecurityVerdict | DKIM verification |
dmarc_verdict | SecurityVerdict | DMARC compliance |
client.inbox.latest(**params)
Get the most recent inbox email. Returns immediately with the latest email or None.
Example
email = client.inbox.latest(to="user@test.com")
if email:
print(f"OTP: {email.detected_otp}")Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
to | str | None | - | Filter by recipient (partial match) |
after | datetime | str | None | - | Only return emails received after this timestamp |
Response Type: InboxEmail | None
| Field | Type | Description |
|---|---|---|
email_id | str | Unique identifier |
detected_otp | str | None | Auto-extracted verification code |
html_body | str | None | HTML content |
text_body | str | None | Plain text content |
from_address | str | Sender email address |
from_name | str | None | Sender display name |
to_addresses | tuple[str, ...] | Recipient addresses |
cc_addresses | tuple[str, ...] | None | CC addresses |
subject | str | None | Email subject |
received_at | datetime | When email was received |
message_id | str | None | SMTP Message-ID header |
has_attachments | bool | Has attachments |
attachment_count | int | Number of attachments |
spam_score | float | None | Spam score |
spam_verdict | PASS | FAIL | GRAY | None | Spam classification |
spam_rules | SpamRules | None | Detailed spam rules |
virus_verdict | SecurityVerdict | Virus scan result |
spf_verdict | SecurityVerdict | SPF authentication |
dkim_verdict | SecurityVerdict | DKIM verification |
dmarc_verdict | SecurityVerdict | DMARC compliance |
client.inbox.get(email_id)
Get a single inbox email by ID.
Example
email = client.inbox.get("550e8400-e29b-41d4-a716-446655440000")
print(f"Subject: {email.subject}")Parameters
| Parameter | Type | Description |
|---|---|---|
email_id | str | The email ID (UUID format) |
Response Type: InboxEmail
Raises NotFoundError if not found.
| Field | Type | Description |
|---|---|---|
email_id | str | Unique identifier |
detected_otp | str | None | Auto-extracted verification code |
html_body | str | None | HTML content |
text_body | str | None | Plain text content |
from_address | str | Sender email address |
from_name | str | None | Sender display name |
to_addresses | tuple[str, ...] | Recipient addresses |
cc_addresses | tuple[str, ...] | None | CC addresses |
subject | str | None | Email subject |
received_at | datetime | When email was received |
message_id | str | None | SMTP Message-ID header |
has_attachments | bool | Has attachments |
attachment_count | int | Number of attachments |
spam_score | float | None | Spam score |
spam_verdict | PASS | FAIL | GRAY | None | Spam classification |
spam_rules | SpamRules | None | Detailed spam rules |
virus_verdict | SecurityVerdict | Virus scan result |
spf_verdict | SecurityVerdict | SPF authentication |
dkim_verdict | SecurityVerdict | DKIM verification |
dmarc_verdict | SecurityVerdict | DMARC compliance |
client.inbox.list(**params)
List inbox email IDs with pagination. Returns only IDs - use get() to fetch full details.
Example
response = client.inbox.list(per_page=20)
for email_id in response:
email = client.inbox.get(email_id)
print(email.subject)Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | int | None | 1 | Page number (1, 2, 3...) |
per_page | int | None | 10 | Results per page (1-100) |
from_ | str | None | - | Filter by sender (partial match) |
to | str | None | - | Filter by recipient (partial match) |
subject | str | None | - | Filter by subject (partial match) |
before | datetime | str | None | - | Emails before this date |
after | datetime | str | None | - | Emails after this date |
Note: Use from_ (with underscore) since from is a Python reserved word.
Response Type: ListIdsResponse
Iterable collection of email IDs with pagination metadata.
| Field | Type | Description |
|---|---|---|
data | tuple[str, ...] | Tuple of email IDs |
pagination.page | int | Current page number |
pagination.per_page | int | Items per page |
pagination.returned | int | Actual count returned |
pagination.has_more | bool | More results available |
Sent Methods
client.sent.latest(**params)
Get the most recent sent email. Returns immediately with the latest email or None.
Example
email = client.sent.latest(to="user@example.com")
if email:
print(f"Spam score: {email.spam_score}")Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
to | str | None | - | Filter by recipient (partial match) |
after | datetime | str | None | - | Only return emails sent after this timestamp |
Response Type: SentEmail | None
| Field | Type | Description |
|---|---|---|
email_id | str | Unique identifier |
detected_otp | str | None | Auto-extracted verification code |
html_body | str | None | HTML content |
text_body | str | None | Plain text content |
from_address | str | Sender email address |
from_name | str | None | Sender display name |
to_addresses | tuple[str, ...] | Recipient addresses |
cc_addresses | tuple[str, ...] | None | CC addresses |
bcc_addresses | tuple[str, ...] | None | BCC addresses |
subject | str | None | Email subject |
sent_at | datetime | When email was sent |
message_id | str | None | SMTP Message-ID header |
has_attachments | bool | Has attachments |
attachment_count | int | Number of attachments |
spam_score | float | None | Spam score |
spam_verdict | PASS | FAIL | GRAY | None | Spam classification |
client.sent.get(email_id)
Get a single sent email by ID.
Example
email = client.sent.get("660f9500-f39c-52e5-b827-557766551111")
print(f"Subject: {email.subject}")Parameters
| Parameter | Type | Description |
|---|---|---|
email_id | str | The email ID (UUID format) |
Response Type: SentEmail
Raises NotFoundError if not found.
| Field | Type | Description |
|---|---|---|
email_id | str | Unique identifier |
detected_otp | str | None | Auto-extracted verification code |
html_body | str | None | HTML content |
text_body | str | None | Plain text content |
from_address | str | Sender email address |
from_name | str | None | Sender display name |
to_addresses | tuple[str, ...] | Recipient addresses |
cc_addresses | tuple[str, ...] | None | CC addresses |
bcc_addresses | tuple[str, ...] | None | BCC addresses |
subject | str | None | Email subject |
sent_at | datetime | When email was sent |
message_id | str | None | SMTP Message-ID header |
has_attachments | bool | Has attachments |
attachment_count | int | Number of attachments |
spam_score | float | None | Spam score |
spam_verdict | PASS | FAIL | GRAY | None | Spam classification |
client.sent.list(**params)
List sent email IDs with pagination. Returns only IDs - use get() to fetch full details.
Example
response = client.sent.list(per_page=20)
for email_id in response:
email = client.sent.get(email_id)
print(email.subject)Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | int | None | 1 | Page number (1, 2, 3...) |
per_page | int | None | 10 | Results per page (1-100) |
from_ | str | None | - | Filter by sender (partial match) |
to | str | None | - | Filter by recipient (partial match) |
subject | str | None | - | Filter by subject (partial match) |
before | datetime | str | None | - | Emails before this date |
after | datetime | str | None | - | Emails after this date |
Response Type: ListIdsResponse
| Field | Type | Description |
|---|---|---|
data | tuple[str, ...] | Tuple of email IDs |
pagination.page | int | Current page number |
pagination.per_page | int | Items per page |
pagination.returned | int | Actual count returned |
pagination.has_more | bool | More results available |
Async Methods
AsyncSigninID provides the same API with await:
import asyncio
from signinid import AsyncSigninID
async def main():
async with AsyncSigninID() as client:
# Wait for new email
email = await client.inbox.wait_for_new(to="user@test.com")
# Get latest
email = await client.inbox.latest(to="user@test.com")
# List and fetch
inbox_ids = await client.inbox.list(to="user@test.com")
for email_id in inbox_ids:
full_email = await client.inbox.get(email_id)
print(full_email.detected_otp)
asyncio.run(main())Error Handling
The SDK raises typed exceptions for different failure scenarios:
| Exception | When Raised |
|---|---|
AuthenticationError | Invalid or missing API key |
NotFoundError | Email not found (404) |
ValidationError | Invalid request parameters |
RateLimitError | Too many requests |
NetworkError | Connection failed |
TimeoutError | Request timed out |
from signinid import (
SigninID,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
NetworkError,
TimeoutError,
)
try:
email = client.inbox.get("invalid-id")
except NotFoundError:
print("Email not found")
except AuthenticationError:
print("Invalid API key")
except ValidationError as e:
print(f"Invalid parameters: {e.details}")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after}s")
except NetworkError:
print("Network error")
except TimeoutError:
print("Request timed out")