Skip to main content
The developer module provides a client for interacting with Apple’s Developer API to manage app IDs, devices, provisioning profiles, and certificates.

DeveloperSession

pub struct DeveloperSession {
    anisette: Arc<Mutex<AnisetteData>>,
    client: Client,
    adsid: String,
    xcode_gs_token: String,
}
Represents an authenticated session with Apple’s Developer API.

Creating a session

use plume_core::auth::Account;
use plume_core::developer::DeveloperSession;

// After authenticating with Account::login()
let session = DeveloperSession::using_account(account).await?;

Methods

using_account
async fn
pub async fn using_account(account: Account) -> Result<Self, Error>
Creates a developer session from an authenticated Account
new
async fn
pub async fn new(
    adsid: String,
    xcode_gs_token: String,
    config: AnisetteConfiguration,
) -> Result<Self, Error>
Creates a session with stored credentials. Validates the session by listing teams.
adsid
fn
pub fn adsid(&self) -> &String
Returns the Apple Directory Services ID for this session
xcode_gs_token
fn
pub fn xcode_gs_token(&self) -> &String
Returns the Xcode GrandSlam token for this session

Teams

Manage Apple Developer teams associated with the account.
qh_list_teams
async fn
pub async fn qh_list_teams(&self) -> Result<TeamsResponse, Error>
Lists all teams associated with the developer account

Team response

pub struct Team {
    pub status: String,
    pub name: String,
    pub team_id: String,
    pub _type: String,
}
let teams = session.qh_list_teams().await?;
for team in teams.teams {
    println!("Team: {} ({})", team.name, team.team_id);
}

App IDs

Manage application identifiers and their capabilities.
qh_list_app_ids
async fn
pub async fn qh_list_app_ids(
    &self,
    team_id: &String
) -> Result<AppIDsResponse, Error>
Lists all app IDs for a team
qh_add_app_id
async fn
pub async fn qh_add_app_id(
    &self,
    team_id: &String,
    name: &String,
    identifier: &String,
) -> Result<AppIDResponse, Error>
Creates a new app ID with the specified bundle identifier
qh_get_app_id
async fn
pub async fn qh_get_app_id(
    &self,
    team_id: &String,
    identifier: &String,
) -> Result<Option<AppID>, Error>
Retrieves a specific app ID by bundle identifier
qh_ensure_app_id
async fn
pub async fn qh_ensure_app_id(
    &self,
    team_id: &String,
    name: &String,
    identifier: &String,
) -> Result<AppID, Error>
Gets an existing app ID or creates it if it doesn’t exist
qh_delete_app_id
async fn
pub async fn qh_delete_app_id(
    &self,
    team_id: &String,
    app_id_id: &String,
) -> Result<QHResponseMeta, Error>
Deletes an app ID
qh_update_app_id
async fn
pub async fn qh_update_app_id(
    &self,
    team_id: &String,
    app_id_id: &String,
    features: Dictionary,
) -> Result<AppIDResponse, Error>
Updates app ID capabilities (push notifications, iCloud, etc.)

AppID struct

pub struct AppID {
    pub app_id_id: String,
    pub identifier: String,
    // ... other fields
}
let team_id = "ABC123XYZ".to_string();
let app_id = session.qh_ensure_app_id(
    &team_id,
    &"My App".to_string(),
    &"com.example.myapp".to_string()
).await?;

println!("App ID: {}", app_id.app_id_id);

App groups

Manage app group identifiers for shared data between apps.
qh_ensure_app_group
async fn
pub async fn qh_ensure_app_group(
    &self,
    team_id: &String,
    name: &String,
    identifier: &String,
) -> Result<ApplicationGroup, Error>
Creates or retrieves an app group
qh_assign_app_group
async fn
pub async fn qh_assign_app_group(
    &self,
    team_id: &String,
    app_id_id: &String,
    app_group_ids: &[String],
) -> Result<QHResponseMeta, Error>
Assigns app groups to an app ID

Provisioning profiles

qh_get_profile
async fn
pub async fn qh_get_profile(
    &self,
    team_id: &String,
    app_id_id: &String,
) -> Result<ProfileResponse, Error>
Generates and retrieves a provisioning profile for an app ID
let profile = session.qh_get_profile(&team_id, &app_id.app_id_id).await?;
let profile_data = profile.provisioning_profile.encoded_profile;

tokio::fs::write("embedded.mobileprovision", &profile_data).await?;

Devices

Manage registered development devices.
qh_list_devices
async fn
pub async fn qh_list_devices(
    &self,
    team_id: &String
) -> Result<DevicesResponse, Error>
Lists all registered devices for a team
qh_add_device
async fn
pub async fn qh_add_device(
    &self,
    team_id: &String,
    name: &String,
    udid: &String,
) -> Result<DeviceResponse, Error>
Registers a new device with its UDID

Request types

pub enum RequestType {
    Get,
    Post,
    Patch,
}
Specifies the HTTP method for API requests.

Low-level API methods

qh_send_request
async fn
pub async fn qh_send_request(
    &self,
    url: &str,
    body: Option<Dictionary>,
) -> Result<Dictionary, Error>
Sends a request to the QuickHelp (QH) API endpoint
v1_send_request
async fn
pub async fn v1_send_request(
    &self,
    url: &str,
    body: Option<serde_json::Value>,
    request_type: Option<RequestType>,
) -> Result<serde_json::Value, Error>
Sends a request to the v1 API endpoint with JSON payload

Capabilities

v1_request_capabilities_for_entitlements
async fn
pub async fn v1_request_capabilities_for_entitlements(
    &self,
    team_id: &String,
    identifier: &String,
    entitlements: &plist::Dictionary,
) -> Result<(), Error>
Automatically enables required capabilities based on app entitlements

Example: Complete workflow

use plume_core::developer::DeveloperSession;

#[tokio::main]
async fn main() -> Result<(), plume_core::Error> {
    let session = DeveloperSession::using_account(account).await?;
    
    // Get team
    let teams = session.qh_list_teams().await?;
    let team_id = &teams.teams[0].team_id;
    
    // Create app ID
    let app_id = session.qh_ensure_app_id(
        team_id,
        &"My App".to_string(),
        &"com.example.myapp".to_string()
    ).await?;
    
    // Get provisioning profile
    let profile = session.qh_get_profile(
        team_id,
        &app_id.app_id_id
    ).await?;
    
    // Save profile
    tokio::fs::write(
        "embedded.mobileprovision",
        &profile.provisioning_profile.encoded_profile
    ).await?;
    
    Ok(())
}

Build docs developers (and LLMs) love