{"id":37051463,"url":"https://github.com/skylab-tech/studio_client_dotnet","last_synced_at":"2026-01-14T05:56:39.171Z","repository":{"id":203623775,"uuid":"710007045","full_name":"skylab-tech/studio_client_dotnet","owner":"skylab-tech","description":".NET Studio Client SDK","archived":false,"fork":false,"pushed_at":"2025-06-18T17:56:39.000Z","size":67,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-29T05:24:52.640Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skylab-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-10-25T20:20:36.000Z","updated_at":"2025-06-18T17:54:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"f7b4d980-ae0d-4373-bd2e-c3cf169901b6","html_url":"https://github.com/skylab-tech/studio_client_dotnet","commit_stats":null,"previous_names":["skylab-tech/studio_client_dotnet"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/skylab-tech/studio_client_dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-tech%2Fstudio_client_dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-tech%2Fstudio_client_dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-tech%2Fstudio_client_dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-tech%2Fstudio_client_dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skylab-tech","download_url":"https://codeload.github.com/skylab-tech/studio_client_dotnet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-tech%2Fstudio_client_dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28412126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T05:56:38.493Z","updated_at":"2026-01-14T05:56:39.162Z","avatar_url":"https://github.com/skylab-tech.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skylab Studio .NET Client\n\n.NET client to interface with Skylab Studio [Public API](https://studio-docs.skylabtech.ai)\n\n## Installation\n\n```bash\n$ nuget install SkylabStudio\n```\n\n## Example Usage\n\nFor all examples, assume:\n\n```dotnet\nusing SkylabStudio;\n\nvar apiClient = new StudioClient(\"YOUR_SKYLAB_API_TOKEN\");\n\n// optional: MaxConcurrentDownloads to configure max concurrent downloads for when using DownloadAllPhotos method\n//  - defaults to 5 concurrent downloads at a time\n// optional: ResizeImageIfOversized to resize oversized images to be below Skylab dimension limit\n//  - defaults to false\n// optional: MaxMemory to configure max memory usage (in megabytes MB) for when using DownloadAllPhotos method\n//  - defaults to 100\n// optional: PngCompression to configure png compression level (value range 0-9)\n//  - defaults to 6\n// optional: PngEffort to configure png effort level (value range 1-9)\n//  - defaults to 7\nvar studioOptions = new StudioOptions { MaxConcurrentDownloads = 5, ResizeImageIfOversized = true, MaxMemory = 100, PngCompression = 6, PngEffort = 7 };\nvar apiClient = new StudioClient(Environment.GetEnvironmentVariable(\"SKYLAB_API_TOKEN\"), studioOptions);\n```\n\n```dotnet\n// Example Job Processing Flow with Callback\n\n// CREATE PROFILE\ndynamic profile = await apiClient.CreateProfile(new { name = $\"Test Profile\", enable_crop = false, enable_color = true });\n\n// CREATE JOB\nvar jobName = $\"test-job\";\ndynamic job = await apiClient.CreateJob(new { name = jobName, profile_id = profile.id.Value });\n\n// UPLOAD PHOTO\nstring filePath = \"/path/to/photo\";\ndynamic res = await apiClient.UploadJobPhoto(filePath, job.id.Value);\n\n// QUEUE JOB\ndynamic queuedJob = await apiClient.QueueJob(job.id.Value, new { callback_url = \"YOUR_CALLBACK_ENDPOINT\" });\n\n// NOTE: Once the job is queued, it will get processed then complete\n// We will send a response to the specified callback_url with the output photo download urls\n```\n\n```dotnet\n// OPTIONAL: If you want this SDK to handle photo downloads to a specified output folder\n\n// FETCH COMPLETED JOB (wait until job status is completed)\ndynamic completedJob = await apiClient.GetJob(queuedJob.id.Value);\n\n// DOWNLOAD COMPLETED JOB PHOTOS\nJArray photosList = completedJob.photos;\nawait apiClient.DownloadAllPhotos(photosList, completedJob.profile, \"photos/output/\");\n```\n\n### Error Handling\n\nBy default, the API calls return a JSON (JObject) response object no matter the type of response.\n\n### Endpoints\n\n#### List all jobs\n\n```dotnet\napi.ListJobs();\n```\n\n#### Create job\n\n```dotnet\napi.CreateJob(new { name = \"Test Job\", profileId = 123 });\n```\n\nFor all payload options, consult the [API documentation](https://studio-docs.skylabtech.ai/#tag/job/operation/createJob).\n\n#### Get job\n\n```dotnet\napi.GetJob(jobId);\n```\n\n#### Update job\n\n```dotnet\napi.UpdateJob(jobId, new { name = \"Updated Job Name\" });\n```\n\nFor all payload options, consult the [API documentation](https://studio-docs.skylabtech.ai/#tag/job/operation/updateJobById).\n\n#### Queue job\n\n```dotnet\napi.QueueJob(jobId, new { callback_url = \"http://your.endpoint/\"});\n```\n\n#### Delete job\n\n```dotnet\napi.DeleteJob(jobId);\n```\n\n#### Cancel job\n\n```dotnet\napi.CancelJob(jobId);\n```\n\n#### Jobs in front\n\nUse after queueing job to check number of jobs ahead of yours\n\n```dotnet\napi.JobsInFront(jobId);\n```\n\n#### List all profiles\n\n```dotnet\napi.ListProfiles();\n```\n\n#### Create profile\n\n```dotnet\napi.CreateProfile(new { name = $\"New Profile\", enable_crop = false, enable_color = true });\n```\n\nFor all payload options, consult the [API documentation](https://studio-docs.skylabtech.ai/#tag/profile/operation/createProfile).\n\n#### Get profile\n\n```dotnet\napi.GetProfile(profileId);\n```\n\n#### Update profile\n\n```dotnet\napi.UpdateProfile(profileId, new { name = $\"Test Profile\", enable_crop = false, enable_color = true });\n```\n\nFor all payload options, consult the [API documentation](https://studio-docs.skylabtech.ai/#tag/profile/operation/updateProfileById).\n\n#### Get photo\n\n```dotnet\napi.GetPhoto(photoId);\n```\n\n#### Upload photo\n\nThis function handles validating a photo, creating a photo object and uploading it to your job/profile's s3 bucket.\n\n```dotnet\napi.UploadJobPhoto(\"/path/to/photo\", jobId);\n```\n\nOR\n\n```dotnet\n// Use the following to upload a background photo for a profile (replace bg enabled)\napi.UploadProfilePhoto(\"/path/to/photo\", profileId);\n```\n\nIf upload fails, the photo object is deleted for you. If upload succeeds and you later decide you no longer want to include that image, use api.DeletePhoto(photoId) to remove it.\n\n#### Download photo(s)\n\nThis function handles downloading the output photos to a specified directory.\n\n```dotnet\nJArray photosList = completedJob.photos;\n\nDownloadAllPhotosResult downloadResults = await apiClient.DownloadAllPhotos(photosList, completedJob.profile, \"/output/folder/path\");\nConsole.WriteLine($\"Success photos: [{string.Join(\", \", downloadResults.SuccessPhotos)}]\");\nConsole.WriteLine($\"Errored photos: [{string.Join(\", \", downloadResults.ErroredPhotos)}]\");\n\nOutput:\nSuccess photos: [1.jpg, 2.jpg, 3.jpg]\nErrored photos: [4.jpg]\n```\n\nOR\n\n```dotnet\napi.DownloadPhoto(photoId, \"/path/to/photo.jpg\"); # accepts full path OR\napi.DownloadPhoto(photoId, \"/path/to/output/folder\"); # accepts directory\n```\n\n#### Delete photo\n\nThis will remove the photo from the job/profile's bucket. Useful for when you've accidentally uploaded an image that you'd like removed.\n\n```dotnet\napi.DeletePhoto(photoId);\n```\n\n#### Validate hmac headers\n\nApplicable if you utilize the job callback url. Use to validate the job payload integrity.\n\n- secretKey (string): Obtain from Skylab\n\n- jobJson (string): Stringified json object obtained from callback PATCH request\n\n- requestTimestamp (string): Obtained from callback PATCH request header 'X-Skylab-Timestamp'\n\n- signature (string): Signature generated by Skylab to compare. Obtained from callback PATCH request header 'X-Skylab-Signature'\n\nReturns **True** or **False** based on whether or not the signatures match.\n\n```dotnet\napi.ValidateHmacHeaders(secretKey, jobJson, requestTimestamp, signature);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylab-tech%2Fstudio_client_dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskylab-tech%2Fstudio_client_dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylab-tech%2Fstudio_client_dotnet/lists"}