Package: pluginlab_admin
python-admin-sdkInstallpipinstallpluginlab_adminGetting startedGet started by initializing the Pluginlab app:frompluginlab_adminimportAppapp=App(secret_key="<PLUGIN_SECRET>",plugin_id="<PLUGIN_ID>",)# to manage auth-related stuff, mostly membersauth=app.get_auth()The SDK secret should be generatedfrom your Pluginlab dashboard.Verify the user tokenEverytime ChatGPT will talk to your backend through the PluginLab proxy, it will send the user token in the Authorization header as a bearer token.
You can verify the integrity of such token by using theverify_tokenmethod:auth=app.get_auth()# usually you'd get the token from the Authorization header of the HTTP request, formatted as `Bearer <token>`token="eyJhbGc...dQssw5c"try:payload=auth.verify_token(token)# from that point we know the information in the token hasn't been tampered with# we could, for instance, check if the user has a given plan and take specific action based on thatpremium_plan_id='KWsmKyJnHBF2Dz1mETDF'plan_id=payload.user.plan_idifplan_id:ifplan_id==premium_plan_id:do_something_special()elsedo_other_stuff()print(payload.uid)exceptExceptionase:print(f"An error occurred while verifying the token:{e}")The verified token payload is represented by the following typings:classTokenPayloadUser:id:stremail:strname:Optional[str]=Nonegiven_name:Optional[str]=Noneplan_id:Optional[str]=Noneprice_id:Optional[str]=NoneclassTokenPayload:uid:striss:straud:striat:intexp:intuser:TokenPayloadUserGet a member by id or emailBy emailmember=auth.get_member_by_email('johndoe@example.com')ifmemberisNone:print('No such member.')elseprint(f'Member with email{member.auth.email}signed up with method "{member.auth.sign_in_method}"')By idmember=auth.get_member_by_id('mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26')ifmemberisNone:print('No such member.')elseprint(f'Member with id{member.id}(email={member.auth.email}) signed up with method "{member.auth.sign_in_method}"')A member is represented with the following typings:classSignInMethodId(Enum):EMAIL_AND_PASSWORD='email-and-password'MAGIC_EMAIL_CODE='magic-email-code'GOOGLE='google'classMemberAuth:is_verified:bool;email:str;has_password:bool;sign_in_method:SignInMethodId;classMember:id:str;auth:MemberAuth;name:Optional[str]given_name:Optional[str]family_name:Optional[str]picture_url:Optional[str]custom_fields:dict[str,str];metadata:dict[str,str];created_at_ms:int;updated_at_ms:int;Get member identitiesOnce a user logs in to your PluginLab portal using a third-party authentication provider, they get assigned an identity for that specific provider.
An identity might contain what you need to interact with the service on behalf of your user such as an access token or a refresh token.
To retrieve all the identities for a given user, use theauth.get_member_identitiesmethod:identities=auth.get_member_identities("mem_66c72702dfd9c9a34e80cae434a4bf7e6d3d37df")ifidentities.googleisnotNone:print("Google identity found, access token is ",identities.google.access_token)ifidentities.githubisnotNone:# do your stuff# This applies to every third-party auth provider supported by PluginLab although each might give or not give some information.Here is the class used to represent an identity:@dataclassclassIdentityProviderData:provider:str;provider_user_id:str;access_token_expires_at_ms:int|None;refresh_token_expires_at_ms:int|None;last_used_at_ms:int|None;access_token:str|None;refresh_token:str|None;List membersBasicpaginated_result=auth.get_members()formemberinpaginated_result.items:print(member.id)With adjustable limit and paginationYou can request up to 100 members at a time and get a specific page by providing a cursor obtained from a previous call.paginated_result1=auth.get_members(50)cursor=paginated_result1.next_page_cursorifnotcursorisNone:paginated_result2=auth.get_members(50,cursor)Create a membercreated_member=auth.create_member(email='johndoe@example.com',password='12345',is_verified=True,metadata={'origin':'backend-sdk'})print(created_member)As the typings show, bothis_verifiedandmetadatafields are optional to create a user.Update a memberauth.update_member(id='mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26',given_name="John the king of examples",family_name="Doe",name="John Doe",picture_url="https://example.com/john-doe.png",metadata={})Except theidfield that is used to identify the user to update, all the other updatable fields are optional in this function call.Delete a memberauth.delete_member(id='mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26',)Note that the member ID is derived from the email the user used to sign up. Therefore recreating an account with the same email will NOT reset usage quotas.Get user quota informationSince version0.4.0you can retrieve the current quota usage of a plugin member thanks to the monetization module:monetization=app.get_monetization();quota_usage=monetization.get_member_quota_usage(member_id);ifquota_usage.is_over_limit:print(f'User exceeded their quota, it will be reset in{quota_usage.reset_in_days}days.')Dealing with webhooksPluginlab signs each webhook payload it sends you using a secret key you can retrieve from yourwebhooks settings on the Pluginlab dashboard.This package provides facilities to easiliy verifiy the payload of a webhook.Here is how, using a flask handler as an example:importosfrompluginlab_adminimportWebhookHeaders,Webhookwebhook_secret=os.getenv('WEBHOOK_SECRET')webhook=Webhook(webhook_secret)@app.route('/webhook',methods=['POST'])defapi():sig=request.headers.get(WebhookHeaders.Signature.value)raw_body=request.get_data(as_text=True)ifnotsig:returnjsonify({'message':'No signature was found.'})ifnotwebhook.is_signature_valid(raw_body,sig):returnjsonify({'message':'Invalid signature.'})// process the payload as you likeMake sure you are providing theis_signature_validmethod with the raw body of the request, as it was originally sent.EventsOn PluginLab, an event is used as a representaiton of a plugin request and is traditionally generated on each request made by ChatGPT.
The SDK offers limited but useful utilities to deal with events.To get started, you need to leverage the event service by calling theapp.get_eventmethod.// assuming app was previously initialized as showed aboveevent=app.get_event();Create a custom eventIf you want to create custom events that will appear in your PluginLab dashboard and count as part of your users' quota, you can rely on thecreate_custommethod.This is especially useful if your service is accessible from other means that ChatGPT but you still want to account for usage using PluginLab.frompluginlab_adminimportEventLocationlocation=EventLocation(country_code="US",subdivision_code="CA",# optional)event.create_custom(# case insensitive, max. 10 charsevent_source="WEB_UI",# optional, quota ignored if not presentmember_id="mem_fd9a1ba5e385e3d97412cdfbd7b8284c4f0c8e18",# optionallocation=location,# optional, defaults to trueis_in_quota=True)Assuming the providedmember_idrefers to a valid plugin member then a new event will get created once the above code runs. It will appear in your PluginLab dashboard's event section.