Go to Dark mode
Go to Light mode

Webhook Documentation - V1.0.0

Introduction

Why use webhooks

Webhooks are a great way to get updates and events that occur on your Unlimited3D account, or on user accounts connected to your app. Using webhook, you will get notified about events happening and can run actions on your backend based on these events.

After registering your webhook endpoint Unlimited3D will push real time notifications to it when events happen in associated accounts. These notifications are sent over HTTPS using JSON as payload, and have signature assigned to them, generated using the secret you get after creating a webhook endpoint, so you can validate that the event was indeed sent by Unlimited3D.

Getting Started

Create webhook endpoint

Process for creating webhook endpoints differs for users and applications.

For users, go to Account -> Webhooks and create a webhook endpoint with a URL to your backend service. If creation is successful you will get a webhook secret. Please save this secret, as you will not be able to see or change it later.

For apps, when contacting our support, please specify that you will want to have a webhook endpoint associated with your app. After the app is created, you will receive webhook secrets alongside app information. Whenever a new user authorizes your app, your webhook endpoint will be registered for that user as well.

Payload format

Payload sent to your webhook endpoint will always be JSON. This JSON payload will always be in following format:

Name Type Description
id string Id of the webhook event, generated by Unlimited3D.
version string API version that indicates the Unlimited3D version used, as well as event format.
time timestamp Time at which event was emited.
type string Type of webhook event. How you will process the event is based on this parameter. Event data will differ based on the event type.
data object Data of the event, containing information necessary to perform actions related to the event. Structure of data depends on the event type.
{
    "id": "123456",
 	"version": "v10",
 	"time": 1632124827,
	"type": "job.finished",
 	"data": {
 		 "res": {}
	}
 }

Receive webhook events

Unlimited3D will send webhook events to your endpoint using the POST method.

Validate signature

First thing your code should do is verify that the event was sent by Unlimited3D by checking the signature that is sent in the payload.

Signature is included in the header of the webhook request. Hash-based message authentication code (HMAC) with SHA-256 is used to generate the signature. In order to validate the signature, you should generate it on your end, using the following process.

Concatenate time (as a string), the ; character and the JSON payload, then compute the HMAC with the SHA256 hash function using this above generated string that and webhook secret as key and compare it to the received signature.

Node.js example code:

const data = req.body;
const headers = req.headers;

const hmac = crypto.createHmac('sha256', YOUR_WEBHOOK_SECRET);
const signature = hmac.update(`${data.time};${data}`).digest('hex');

// You can now compare generated signature
// with the one received in request header
signature === headers['u3d-signature']

If signatures do not match, do not proceed, as you can not be sure that the event was sent by Unlimited3D. If signatures match, you can proceed with your logic related to that event.

Validate time

We also recommend that you compare time in the request with your server's current time to validate if the difference is within your tolerance.

Return a 2xx status code

To mark an event received your endpoint must return a 2xx HTTP status code to Unlimited3D. All other response codes outside this range including 3xx will indicate that you did not receive the webhook event.

Error handling and event resending

If your endpoint can not be contacted, or return non 2xx HTPP status code, Unlimited3D will automatically start the retry process. Basically Unlmited3D will keep sending the event to your endpoint in predefined periods and up to 7 times, until the event is confirmed to be successfully received.

We call this event lifecycle and it is as following:

  • First webhook event sent
  • 5 mins after 1st sent&fail
  • 1 hour after 2nd sent&fail
  • 24 hours after 3td sent&fail
  • 24 hours after 4th sent&fail
  • 24 hours after 5th sent&fail
  • 24 hours after 6th sent&fail
  • After 7th sent&fail we will stop sending webhook event


Event Types and Results

Introduction

Event types specify what happened on the user's account and what action your application should perform. Event’s data is different based on the event type and corresponds to data presented in this section.

This section lists all currently available event types. This document will be updated with all new event types as they are added.

Job Finished

Job finished is sent when the job queued using third party API finishes processing.

Name Type Description
id string Id of the job
status string Indicates the status of the job. Can be either finished or in_progress.
type string Type of the job. Currently supported types are: AddModelToSolution, PublishSolution, ConvertModel and UploadOptimizeModel.
result object Result of the job. Schema depends on the job type.
errors array Array of errors connected to the job. Empty array indicates that there were no errors while processing the job.
warnings array Array of warnings connected to the job. Empty array indicates that there were no warnings while processing the job.

Data schema for this event is as following:

{
   "id": "14456",
   "status": "finished",
   "type": "AddModelToSolution",
   "result": {},
   "errors": [],
   "warnings": []
}


Results of the Job

Schema depends on the job type.


AddModelToSolution

Returns ID and URL of the solution to which the model was added.

{
	"solutionID":12932,
	"solutionURL":"https:\/\/unlimited3d.com\/app\/projects\/321\/solutions\/12932"
}


PublishSolution

Contains information about the newly created distribution of the solution.

{
	"id": "5540",
	"status": "live",
	"note": "",
	"link": "https://dist.unlimited3d.com/dists/project-name/test-auto/12932/5540",
	"script_link": "https://cdn.unlimited3d.com/pres/v/2.0.0-b1/unlimited3d.min.js",
	"solution3d_id": "12932",
	"slug_solution3d_name": "test-auto",
	"slug_project_name": "project-name",
	"distribution_version": "2.0.0-b1",
	"stop_after_date": null,
	"pause_date_views": null,
	"created_at": "2021-10-20T12:24:04.000000Z",
	"updated_at": "2021-10-20T12:24:06.000000Z"
}


ConvertModel

Contains URL of the converted model.

{
 "url":"https://s3.eu-west-2.amazonaws.com/storage.unlimited3d.com/userdata/7/addModelTmp/98b67652-62e0-41f1-ba0c-4cd337e326f8/test.glb?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAQNQF6R7YA4NUY3XP%2F20220704%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220704T101903Z&X-Amz-SignedHeaders=host&X-Amz-Expires=54480&X-Amz-Signature=1931da6d85e0742d544b4f3170cf3c365b2fe3829c58aa55e1ab024dfc967846"
}


UploadOptimizeModel

Contains the information about exported optimized model.

{
 "optimized_model":{
   "tags":["first", "second"],
   "modelname":"model_test",
   "urls":{
    "model_optimized.usdz":"https://s3.eu-west-2.amazonaws.com/storage.unlimited3d.com/userdata/7/addModelTmp/model_test-2854/model_optimized.usdz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAQNQF6R7YMJMX5UXZ%2F20220704%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220704T105723Z&X-Amz-Expires=86400&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGMaCWV1LXdlc3QtMiJIMEYCIQDUjPEZf7U2K0VvQmrstILXoY5aKCI9fryKK0xJs9eEwwIhALRvf1ZtB9VGnoim8nWEPz%2FSqCtRFo9wxR873UrYMoFiKqsCCIz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQAhoMMDI5MDAzNTE3OTM2IgxszdgmokqXRIT5JvUq%2FwGalRkCS8sVHYOkR89Kja7fI8DY3T2y3w06mZG78cF0hvVjR5oIVXI1IY1knDevsY7Vf6S4iLPIeoeI%2FlH0rL260q9jG6jiKiT08e%2BQ54wG6lTO7udcJpNWTtuKXOV5fGzkomceuq3StRqWmU%2FZzzwMs0EH0TT4tXrdblL8mniXUk97Pqux5G4rrw0dbF44owT%2FErOI7c38YvOawIiWkxBzH%2B7QZcpQQc6jUblU1Vb7zzFT%2B%2BBwlUkcDTVAGITEG9QnGosGISEVwfsZJQ4bjLnSxihsYA4XtrA0nLhkYM0owv44UbrAkauTU9Q8TNbGZWiKN5iOSEuPigGVLxuXmmEwkY%2BLlgY6mQFVqWwEH4aX87WREz%2BYYzr6BdWk6HCE2tbe1sChojuL3LFIm%2BD0SLJC2e5XAGSQipHuSc2gXuJFVvhDd4qZtdPY6SMrINngi1t%2FTaf%2F1ZG3CjhmZxhGHbQiIfCI9scr2o74S22FROLUfixGEy45wGoPY6iG8RecKt7Dyl7iXEl4Hl34uBsoEDxP1yht7KPvPkU9ECQxlIn0jHI%3D&X-Amz-Signature=af47ae471237265a48d5476af6d1bc7acbe1c959bb4782a0323ce44eabbab790&X-Amz-SignedHeaders=host"
    "model_optimized.glb":"https://s3.eu-west-2.amazonaws.com/storage.unlimited3d.com/userdata/7/addModelTmp/model_test-2854/model_optimized.glb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAQNQF6R7YMJMX5UXZ%2F20220704%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220704T105724Z&X-Amz-Expires=86400&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGMaCWV1LXdlc3QtMiJIMEYCIQDUjPEZf7U2K0VvQmrstILXoY5aKCI9fryKK0xJs9eEwwIhALRvf1ZtB9VGnoim8nWEPz%2FSqCtRFo9wxR873UrYMoFiKqsCCIz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQAhoMMDI5MDAzNTE3OTM2IgxszdgmokqXRIT5JvUq%2FwGalRkCS8sVHYOkR89Kja7fI8DY3T2y3w06mZG78cF0hvVjR5oIVXI1IY1knDevsY7Vf6S4iLPIeoeI%2FlH0rL260q9jG6jiKiT08e%2BQ54wG6lTO7udcJpNWTtuKXOV5fGzkomceuq3StRqWmU%2FZzzwMs0EH0TT4tXrdblL8mniXUk97Pqux5G4rrw0dbF44owT%2FErOI7c38YvOawIiWkxBzH%2B7QZcpQQc6jUblU1Vb7zzFT%2B%2BBwlUkcDTVAGITEG9QnGosGISEVwfsZJQ4bjLnSxihsYA4XtrA0nLhkYM0owv44UbrAkauTU9Q8TNbGZWiKN5iOSEuPigGVLxuXmmEwkY%2BLlgY6mQFVqWwEH4aX87WREz%2BYYzr6BdWk6HCE2tbe1sChojuL3LFIm%2BD0SLJC2e5XAGSQipHuSc2gXuJFVvhDd4qZtdPY6SMrINngi1t%2FTaf%2F1ZG3CjhmZxhGHbQiIfCI9scr2o74S22FROLUfixGEy45wGoPY6iG8RecKt7Dyl7iXEl4Hl34uBsoEDxP1yht7KPvPkU9ECQxlIn0jHI%3D&X-Amz-Signature=791d83d593571bd63d178c23eb307a9cf024cd569369e57e63643c1bde5956ad&X-Amz-SignedHeaders=host"
   }
 }
}

Solution Published

This event is sent when user's solution is published.

Data shema for this event is as following:

{
	"id": "5540",
	"status": "live",
	"note": "",
	"link": "https://dist.unlimited3d.com/dists/project-name/test-auto/12932/5540",
	"script_link": "https://cdn.unlimited3d.com/pres/v/2.0.0-b1/unlimited3d.min.js",
	"solution3d_id": "12932",
	"slug_solution3d_name": "test-auto",
	"slug_project_name": "project-name",
	"distribution_version": "2.0.0-b1",
	"stop_after_date": null,
	"pause_date_views": null,
	"created_at": "2021-10-20T12:24:04.000000Z",
	"updated_at": "2021-10-20T12:24:06.000000Z"
}