Official Python SDK for Original API
- Getting Started
- Documentation
Ensure you have registered for an account at Original before getting started. You will need to create an app and note down your API key and secret from the API Keys page to use the Original SDK.
Install Original
$ pip install original-sdk
The Original SDK is set up to expose the Original API.
Read the full Original API documentation.
Create a new instance of the Original client by passing in your api key and secret, with the environment associated with that app.
For development apps, you must pass the environment:
from original_sdk import OriginalClient, Environment
client = OriginalClient(api_key='YOUR_DEV_APP_API_KEY', api_secret='YOUR_DEV_APP_SECRET', env=Environment.Development)
For production apps, you can optionally pass the production environment:
from original_sdk import OriginalClient, Environment
client = OriginalClient(api_key='YOUR_PROD_APP_API_KEY', api_secret='YOUR_PROD_APP_SECRET', env=Environment.Production)
or omit the environment, which will default to production:
from original_sdk import OriginalClient
client = OriginalClient(api_key='YOUR_PROD_APP_API_KEY', api_secret='YOUR_PROD_APP_SECRET')
There is also an async client available for use with async/await syntax:
from original_sdk import OriginalAsyncClient, Environment
client = OriginalAsyncClient(api_key='YOUR_DEV_APP_API_KEY', api_secret='YOUR_DEV_APP_SECRET', env=Environment.Development)
The user methods exposed by the sdk are used to create and retrieve users from the Original API.
# Returns a response object. Access the user's UID through the `data` attribute.
create_response = client.create_user()
new_user_uid = create_response['data']['uid']
# Sample create_response:
{
"success": True,
"data": {
"uid": "175324281338"
}
}
# You can also pass in a user_external_id and/or email for your external reference.
# The user_external_id and/or email supplied must be unique per app
create_response = client.create_user(email='YOUR_EMAIL', user_external_id='YOUR_USER_EXTERNAL_ID')
new_user_uid = create_response['data']['uid']
# ...
# Get a user by UID
# Returns their details in a response object if the user exists. If not, a 404 client error will be raised.
user_response = client.get_user(new_user_uid)
user_details = user_response['data'] # Contains user details such as UID, email, etc.
# Sample user_response:
{
"success": True,
"data": {
"uid": "754566475542",
"user_external_id": "user_external_id_1",
"created_at": "2024-02-26T13:12:31.798296Z",
"email": "user_email@email.com",
"wallets": [
{
"address": "0x1d6169328e0a2e0a0709115d1860c682cf8d1398",
"chain_id": 80001,
"explorer_url": "https://amoy.polygonscan.com/address/0x1d6169328e0a2e0a0709115d1860c682cf8d1398"
"network": "Amoy",
}
]
}
}
# Get a user by email
# Attempts to retrieve a user by their email address. If the user does not exist, `data` will be None.
user_by_email_response = client.get_user_by_email('YOUR_EMAIL')
user_by_email_details = user_by_email_response['data']
# Sample user_by_email_response on success:
{
"success": True,
"data": {
"uid": "754566475542",
"user_external_id": "user_external_id_1",
"created_at": "2024-02-26T13:12:31.798296Z",
"email": "user_email@email.com",
"wallet_address": "0xa22f2dfe189ed3d16bb5bda5e5763b2919058e40"
}
}
# Sample user_by_email_response (if user does not exist) on failure
{
"success": False,
"data": None
}
# Get a user by user external ID
# Retrieves a user by their user external ID. If the user does not exist, `data` will be None.
user_by_user_external_id_response = client.get_user_by_user_external_id('YOUR_USER_EXTERNAL_ID')
user_by_user_external_details = user_by_user_external_id_response['data']
# Sample user_by_user_external_id_response on success:
{
"success": True,
"data": {
"uid": "754566475542",
"user_external_id": "user_external_id",
"created_at": "2024-02-26T13:12:31.798296Z",
"email": "user_email@email.com",
"wallet_address": "0xa22f2dfe189ed3d16bb5bda5e5763b2919058e40"
}
}
# Sample user_by_user_external_id_response on failure:
{
"success": False,
"data": None
}
The asset methods exposed by the sdk are used to create (mint) assets and retrieve assets from the Original API.
# prepare the new asset params
new_asset_params = {
"user_uid": "324167489835",
"asset_external_id": "asset_external_id_1",
"collection_uid": "221137489875",
"sale_price_in_usd": 9.99,
"data": {
"name": "Dave Starbelly",
"unique_name": True,
"image_url": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png",
"store_image_on_ipfs": True,
"description": "Friendly OpenSea Creature that enjoys long swims in the ocean.",
"external_url": "https://openseacreatures.io/3",
"attributes": [
{
"trait_type": "Base",
"value": "Starfish"
},
{
"trait_type": "Stamina Increase",
"display_type": "boost_percentage",
"value": 10
},
]
}
}
# Create a new asset
create_asset_response = client.create_asset(**new_asset_params)
new_asset_uid = create_asset_response['data']['uid']
# Sample create_asset_response:
{
"success": True,
"data": {
"uid": "151854912345"
}
}
# Get an asset by UID, returns the asset details in a response object if the asset exists. If not, a 404 client error will be raised.
asset_response = client.get_asset(new_asset_uid)
asset_details = asset_response['data']
# Sample asset_response:
{
"success": True,
"data": {
"uid": "151854912345",
"name": "random name #2",
"asset_external_id": "asset_external_id_1",
"collection_uid": "471616646163",
"collection_name": "Test SDK Collection 1",
"token_id": 2,
"created_at": "2024-02-16T11:33:19.577827Z",
"is_minted": True,
"is_burned": False,
"is_transferring": False,
"is_transferable": True,
"is_editing": False,
"mint_for_user_uid": "885810911461",
"owner_user_uid": "885810911461",
"owner_address": "0x32e28bfe647939d073d39113c697a11e3065ea97",
"metadata": {
"name": "random name",
"image": "https://cryptopunks.app/cryptopunks/cryptopunk1081.png",
"description": "nft_description",
"original_id": "151854912345",
"external_url": "external_url@example.com",
"org_image_url": "https://cryptopunks.app/cryptopunks/cryptopunk1081.png",
"attributes": [
{
"trait_type": "Stamina Increase",
"display_type": "boost_percentage",
"value": 10
}
]
},
"explorer_url": "https://mumbai.polygonscan.com/token/0x124a6755ee787153bb6228463d5dc3a02890a7db?a=2",
"token_uri": "https://storage.googleapis.com/{...}.json"
}
}
# Get assets by the owner's UID
assets_response = client.get_assets_by_user_uid("user_uid")
assets_list = assets_response['data']
# Sample assets_response (showing one asset for brevity, wrapped in a response object):
{
"success": True,
"data": [
{
"uid": "151854912345",
"name": "random name #2",
"asset_external_id": "asset_external_id_1",
"collection_uid": "471616646163",
"collection_name": "Test SDK Collection 1",
"token_id": 2,
"created_at": "2024-02-16T11:33:19.577827Z",
"is_minted": True,
"is_burned": False,
"is_transferring": False,
"is_transferable": True,
"is_editing": False,
"mint_for_user_uid": "885810911461",
"owner_user_uid": "885810911461",
"owner_address": "0x32e28bfe647939d073d39113c697a11e3065ea97",
"metadata": {
"name": "random name",
"image": "https://cryptopunks.app/cryptopunks/cryptopunk1081.png",
"description": "nft_description",
"original_id": "151854912345",
"external_url": "external_url@example.com",
"org_image_url": "https://cryptopunks.app/cryptopunks/cryptopunk1081.png",
"attributes": [
{
"trait_type": "Stamina Increase",
"display_type": "boost_percentage",
"value": 10
}
]
},
"explorer_url": "https://mumbai.polygonscan.com/token/0x124a6755ee787153bb6228463d5dc3a02890a7db?a=2",
"token_uri": "https://storage.googleapis.com/original-production-media/data/metadata/9ac0dad4-75ae-4406-94fd-1a0f6bf75db3.json"
}
# Additional assets would be listed here
]
}
NOTE: Editing an asset will overwrite the existing asset data with the new data provided. If you want to maintain any of the existing data, you must include it in the new data.
NOTE: You must include all the required fields. See https://docs.getoriginal.com/docs/edit-asset for more information.
# prepare the edit asset params
edit_asset_params = {
"data": {
"name": "Dave Starbelly Edited",
"unique_name": True,
"image_url": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png",
"description": "Friendly OpenSea Creature that enjoys long swims in the ocean. Edited",
"attributes": [
{
"trait_type": "Base",
"value": "Starfish"
},
]
}
}
# Edits an asset by UID, by passing in the new asset data
edit_asset_response = client.edit_asset(new_asset_uid, **edit_asset_params)
edit_success = edit_asset_response['success']
# Sample edit_asset_response:
{
"success": True,
"data": None
}
The transfer methods exposed by the sdk are used to transfer assets from one user to another wallet.
# Prepare the transfer parameters
transfer_params = {
"asset_uid": "708469717542",
"from_user_uid": "149997600351",
"to_address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}
# Create a transfer of an asset
transfer_response = client.create_transfer(**transfer_params)
transfer_uid = transfer_response['data']['uid']
# Sample transfer_response:
{
"success": True,
"data": {
"uid": "883072660397"
}
}
# Get a transfer by transfer UID, will throw a 404 Not Found error if the transfer does not exist
transfer_response = client.get_transfer("883072660397")
transfer_details = transfer_response['data']
# Sample transfer_response:
{
"success": True,
"data": {
"uid": "883072660397",
"status": "done",
"asset_uid": "708469717542",
"from_user_uid": "149997600351",
"to_address": "0xe02522d0ac9f53e35a56f42cd5e54fc7b5a12f05",
"created_at": "2024-02-26T10:20:17.668254Z"
}
}
# Get transfers by user UID
transfers_response = client.get_transfers_by_user_uid("149997600351")
transfers_list = transfers_response['data']
# Sample transfers_response:
{
"success": True,
"data": [
{
"uid": "883072660397",
"status": "done",
"asset_uid": "708469717542",
"from_user_uid": "149997600351",
"to_address": "0xe02522d0ac9f53e35a56f42cd5e54fc7b5a12f05",
"created_at": "2024-02-26T10:20:17.668254Z"
}
# Additional transfers would be listed here
]
}
The burn methods exposed by the sdk are used to burn assets from a user's wallet.
# Prepare the burn parameters
burn_params = {
"asset_uid": "708469717542",
"from_user_uid": "483581848722",
}
# Create a burn of an asset
burn_response = client.create_burn(**burn_params)
burn_uid = burn_response['data']['uid']
# Sample burn_response:
{
"success": True,
"data": {
"uid": "365684656925",
}
}
# Get a burn by UID, will throw a 404 Not Found error if the burn does not exist
burn_response = client.get_burn("365684656925")
burn_details = burn_response['data']
# Sample burn_response:
{
"success": True,
"data": {
"uid": "365684656925",
"status": "done",
"asset_uid": "708469717542",
"from_user_uid": "483581848722",
"created_at": "2024-02-26T10:20:17.668254Z"
}
}
# Get burns by user UID
burns_response = client.get_burns_by_user_uid("483581848722")
burns_list = burns_response['data']
# Sample burns_response:
{
"success": True,
"data": [
{
"uid": "365684656925",
"status": "done",
"asset_uid": "708469717542",
"from_user_uid": "483581848722",
"created_at": "2024-02-26T10:22:47.848973Z"
}
# Additional burns would be listed here
]
}
The deposit methods exposed by the sdk are used to return the details for depositing assets.
# Get deposit details for a user and collection
deposit_response = client.get_deposit("user_uid", "collection_uid")
deposit_details = deposit_response['data']
# Sample deposit_response:
{
"success": True,
"data": {
"network": "Amoy",
"chain_id": 80002,
"wallet_address": "0x1d6169328e0a2e0a0709115d1860c682cf8d1398",
"qr_code_data": "ethereum:0x1d6169328e0a2e0a0709115d1860c682cf8d1398@80001"
}
}
The collection methods exposed by the sdk are used to retrieve collection details from the Original API.
# Get a collection by UID, will throw a 404 Not Found error if the collection does not exist
collection_response = client.get_collection('221137489875')
collection_details = collection_response['data']
# Sample collection_response:
{
"success": True,
"data": {
"uid": "471616646163",
"name": "Test SDK Collection 1",
"status": "deployed",
"type": "ERC721",
"created_at": "2024-02-13T10:45:56.952745Z",
"editable_assets": True,
"contract_address": "0x124a6755ee787153bb6228463d5dc3a02890a7db",
"symbol": "SYM",
"description": "Description of the collection",
"explorer_url": "https://mumbai.polygonscan.com/address/0x124a6755ee787153bb6228463d5dc3a02890a7db"
}
}
The allocation methods exposed by the sdk are used to create and retrieve allocations from the Original API.
# Prepare the allocation parameters
allocation_params = {
"amount": 123.123,
"nonce": "nonce1",
"to_user_uid": "483581848722",
"reward_uid": "708469717542",
}
# Create an allocation
allocation_response = client.create_allocation(**allocation_params)
allocation_uid = allocation_response['data']['uid']
# Sample allocation_response:
{
"success": True,
"data": {
"uid": "365684656925",
}
}
# Get an allocation by UID, will throw a 404 Not Found error if the allocation does not exist
allocation_response = client.get_allocation("365684656925")
allocation_details = allocation_response['data']
# Sample allocation_response:
{
"success": True,
"data": {
"uid": "365684656925",
"status": "done",
"reward_uid": "reward_uid",
"to_user_uid": "754566475542",
"amount": 123.123,
"nonce": "nonce1",
"created_at": "2024-02-16T11:33:19.577827Z"
}
}
# Get allocations by user UID
allocations_response = client.get_allocations_by_user_uid("483581848722")
allocations_list = allocations_response['data']
# Sample allocations_response:
{
"success": True,
"data": [
{
"uid": "365684656925",
"status": "done",
"reward_uid": "reward_uid",
"to_user_uid": "754566475542",
"amount": 123.123,
"nonce": "nonce1",
"created_at": "2024-02-16T11:33:19.577827Z"
}
# Additional allocations would be listed here
]
}
The claim methods exposed by the sdk are used to create and retrieve claims from the Original API.
# Prepare the claim parameters
claim_params = {
"from_user_uid": "483581848722",
"reward_uid": "708469717542",
"to_address": '0x4881ab2f73c48a54b907a8b697b270f490768e6d'
}
# Create a claim
claim_response = client.create_claim(**claim_params)
claim_uid = claim_response['data']['uid']
# Sample claim_response:
{
"success": True,
"data": {
"uid": "365684656925",
}
}
# Get a claim by UID, will throw a 404 Not Found error if the claim does not exist
claim_response = client.get_claim("365684656925")
claim_details = claim_response['data']
# Sample claim_response:
{
"success": True,
"data": {
"uid": "365684656925",
"status": "done",
"reward_uid": "708469717542",
"from_user_uid": "754566475542",
"to_address": "0x4881ab2f73c48a54b907a8b697b270f490768e6d",
"amount": 123.123,
"created_at": "2024-02-16T11:33:19.577827Z"
}
}
# Get claims by user UID
claims_response = client.get_claims_by_user_uid("483581848722")
claims_list = claims_response['data']
# Sample claims_response:
{
"success": True,
"data": [
{
"uid": "365684656925",
"status": "done",
"reward_uid": "708469717542",
"from_user_uid": "754566475542",
"to_address": "0x4881ab2f73c48a54b907a8b697b270f490768e6d",
"amount": 123.123,
"created_at": "2024-02-16T11:33:19.577827Z"
}
# Additional claims would be listed here
]
}
The reward methods exposed by the sdk are used to retrieve reward details from the Original API.
# Get a reward by UID, will throw a 404 Not Found error if the reward does not exist
reward_response = client.get_reward('221137489875')
reward_details = reward_response['data']
# Sample reward_response:
{
"success": True,
"data": {
"uid": "151854912345",
"name": "Test SDK Reward 1",
"status": "deployed",
"token_type": "ERC20",
"token_name": "TestnetORI",
"created_at": "2024-02-13T10:45:56.952745Z",
"contract_address": "0x124a6755ee787153bb6228463d5dc3a02890a7db",
"withdraw_receiver": "0x4881ab2f73c48a54b907a8b697b270f490768e6d",
"description": "Description of the reward",
"explorer_url": "https://mumbai.polygonscan.com/address/0x124a6755ee787153bb6228463d5dc3a02890a7db"
}
}
# Get a user's reward balance, will throw a 404 Not Found error if the reward does not exist
reward_response = client.get_balance(reward_uid='221137489875', user_uid='754566475542')
reward_details = reward_response['data']
# Sample reward_response:
{
"success": True,
"data": {
"reward_uid": "221137489875",
"user_uid": "754566475542",
"amount": 100.0
}
}
If something goes wrong, you will receive well typed error messages.
class ClientError(OriginalError): ...
class ServerError(OriginalError): ...
class ValidationError(OriginalError): ...
All errors inherit from an OriginalError
class where you can access the standard properties from the Exception
class as well as the following:
class OriginalErrorCode(Enum):
client_error = "client_error"
server_error = "server_error"
validation_error = "validation_error"
class OriginalError(Exception):
def __init__(self, message, status, data, code):
self.message = message
self.status = status
self.data = data
self.code = code.value # 'client_error' | 'server_error' | 'validation_error'
}
So when an error occurs, you can either catch all using the OriginalError class:
from original_sdk import OriginalError
try:
result = client.create_user(email='invalid_email', user_external_id='user_external_id');
except OriginalError as e:
# handle all errors
or specific errors:
from original_sdk import ClientError, ServerError, ValidationError
try:
result = client.create_user(email='invalid_email', user_external_id='user_external_id');
except ClientError as e:
# handle client errors
except ServerError as e:
# handle server errors
except ValidationError as e:
# handle validation errors
The error will have this structure:
except OriginalError as error:
# error.code == 'client_error' | 'server_error' | 'validation_error'
# error.status == 400 | 404 | ...
# error.message == 'Not Found' | 'Enter a valid email address.' | ...
# error.data == {
# "success": False,
# "error": {
# "type": "validation_error",
# "detail": {
# "code": "invalid",
# "message": "Enter a valid email address.",
# "field_name": "email"
# }
# }
# }
Please note, if you plan to parse the error detail, it can also be an array if there are multiple errors.
# ...
# "detail": [
# {
# "code": "null",
# "message": "This field may not be null.",
# "field_name": "user_external_id"
# },
# {
# "code": "invalid",
# "message": "Enter a valid email address.",
# "field_name": "email"
# }
# ]
If it's a client (SDK) error and not a json response error from our server/REST API, we will return data as a string.
# "error.data": "Not Found"
# "error.status": 404
# "error.code": "client_error"