Skip to main content
Version: v2.5.0

Unionavatar

Introduction

Union Avatars develop and provide identity tools for the Metaverse through Avatars. We work with cutting-edge technologies such as Computer vision, Artificial Intelligence, and blockchain to deliver our product for upcoming immersive paradigms.

The Union Avatars is a tool for companies and users to manage their digital identity as an avatar on web3.0. Current API is an early approach to onboard people as an avatar in the metaverse. It allows them to create photorealistic 3D avatars from 2D Selfie pictures and be part of this digital revolution.

You can find more about us on our website.

Now we will run over some of the main concepts of our API.

Authentication

Get API Acccess

In the beginning, you will need to have your credentials. You can request for it in this page.

Organizations

First, you need to get familiarized with Organizations. Organizations in Union Avatars are the ones that contain users, clothes and avatars. When you get access to our API, you will receive one as well as and an administrator account (for that organization).

It is required to have an organization in order to use our API.

Whenever one of your users logins, creates an avatar, changes clothes,... All of that must be done under your organization.

To use your it, simply pass the Organization ID in the login endpoint. Here is an example:

Content-Type

Put attention to "Content-Type" header value in this request, it must be "application/x-www-form-urlencoded".

js
const url = 'https://api.unionavatars.com/v2/login'
const myHeaders = new Headers()
myHeaders.append('Content-Type', 'application/x-www-form-urlencoded')
const login = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({username: '<YOUR_USERNAME>', password: '<YOUR_PASSWORD>', organization: '<YOUR_ORG_ID>'})
})
.then(res => res.json())
.then(res => console.log(res))
}
login()
js
const url = 'https://api.unionavatars.com/v2/login'
const myHeaders = new Headers()
myHeaders.append('Content-Type', 'application/x-www-form-urlencoded')
const login = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({username: '<YOUR_USERNAME>', password: '<YOUR_PASSWORD>', organization: '<YOUR_ORG_ID>'})
})
.then(res => res.json())
.then(res => console.log(res))
}
login()

Bearer Token

Most of endpoints are protected by bearer JWT, so you will need to provide a specific Authorization header in each request you make to our API.

What you can and can't do will depend on the user's role. The following action require admin previlages.

  • Manage users
  • Manage organization
  • Manage API Keys
Content-Type

Some API calls require an API Key instead of a bearer token, such as creating users in your account!

Response model from /login endpoint looks like:

{ "access_token": "<YOUR_TOKEN>", "token_type": "bearer" }
{ "access_token": "<YOUR_TOKEN>", "token_type": "bearer" }

So the header you will need to add to your request is:

js
const myHeaders = new Headers();
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>');
js
const myHeaders = new Headers();
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>');

API Keys

The last concept about auth that we will cover are API Keys. API Keys can be used instead of Bearer Tokens to act in behalf of an admin user. More importantly, some endpoints will only allow you to use an API Key.

API Key protected endpoints

The following endpoints can only be called with an API Key:

  • POST /users

In order to request an api key you would need to follow the previous section to retrive your token

Admin requirement

The creation and retrieving of API keys requires admin privilege

To create a new key, send a POST request to https://api.unionavatars.com/v2/keys with the following payload:

{ "description": "My very fist API Key", "expire_at": "2030-11-11T11:11:11", "scope": "basic" }
{ "description": "My very fist API Key", "expire_at": "2030-11-11T11:11:11", "scope": "basic" }
js
const url = 'https://api.unionavatars.com/v2/keys'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'POST',
heders: myHeaders,
body: JSON.stringify({
"description": "My very fist API Key",
"expire_at": "2030-11-11T11:11:11",
"scope": "basic"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()
js
const url = 'https://api.unionavatars.com/v2/keys'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'POST',
heders: myHeaders,
body: JSON.stringify({
"description": "My very fist API Key",
"expire_at": "2030-11-11T11:11:11",
"scope": "basic"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()
Keep you API keys safe

Try to keep a record of your api-keys. So in case of any leak attempt you can delete the key.

If you have any issues related to authorization, you can check the troubleshooting section.

Assets (Avatar's clothes and accesories)

Asset classification

Union Avatars API has 3 types of assets:

  • Outfits
  • Garments
  • Hairs

Each asset belongs to a Collection which designates a group of assets that have some kind of relation (theme, campaign,...).

On top of that we have the Catalogues, which are a container of collections and individual assets. Each organization has one catalogue by default, and that catalogue is what will be displayed during the avatar creation. For most of the cases, you will only need to use this.

Collections are also connected to Brands, which are only used for better organization.

Only for outfits and garments

The previous classification only applies to Outfits and Garments. Hairstyles do not apply.

We know this got confusing, but we will go over each one of these now.

Pagination

The following endpoints return paginated data for an easier display on the frontend. This section is not about a specific router but a new way to work with almost all the GET endpoints you will interact with.

The structure of the response of the endpoints that can be paginated will be like the following:

json
{
"items": [ ... ],
"total": integer,
"page": integer,
"size": integer,
"pages": integer
}
json
{
"items": [ ... ],
"total": integer,
"page": integer,
"size": integer,
"pages": integer
}

Inside the array items key you will find the elements you are requesting for.

The total is the number of the total elements you can get from this endpoint (not the number of elements actually recovered).

The page is the pointer that tells you from which page are you retrieving the information. This value will be always 1 or greater. Default is 1.

The size is an integer between 1 and 100 that you can use to specify how much elements you want get for each page. The default is 50.

The pages tell you the number of pages you can request for. It is a quick math total/size.

When making a request to any paginated endpoint you can provide size and page as query parameter to control what elements you want to retrieve.

Outfits, Garments & Hairs

The way to fetch the available assets for your organization is to use your catalogue. If you don't know your catalogue ID, you can perform a simple GET request to /catalogues.

The endpoint we are going to use is: /catalogues/assets/{catalogue_id}

This endpoint has multiple parameters that let you filter which assets you want to receive. Remember that the output will always be paginated (as explained in the previous section).

The main parameters of the endpoint are the following:

  • asset_type: outfits || garments || hairs
  • gender: male || female
  • version: v{versionNumber}
  • brand_id: {brandId}
  • collection_id: {collectionID}

Here's an example on how to get a list of available outfits for male avatars:

js
const url = 'https://api.unionavatars.com/v2/catalogues/assets/{catalogue_id}'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'GET',
heders: myHeaders,
body: JSON.stringify({
"asset_type": "outfits",
"gender": "male"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()
js
const url = 'https://api.unionavatars.com/v2/catalogues/assets/{catalogue_id}'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'GET',
heders: myHeaders,
body: JSON.stringify({
"asset_type": "outfits",
"gender": "male"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()
Same for Hairs and Garments

To get hairs and garments you can use the same snippet, just change the asset_type parameter.

Assembling an outfit with Garments

Instead of using a full outfit, you can compose a new one using Garments. Garments are individual pieces of clothing that can be combined to create an outfit.

There are 4 types of garments:

  • Accessories (optional)
  • Top
  • Bottom
  • Shoes
Get the garments

You can get a list of the available garments by following the instructions in the previous section.

To create a new outfit from a set of garments you need to make a POST request to /outfits/assemble:

js
const url = 'https://api.unionavatars.com/v2/outfits/assemble'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'POST',
heders: myHeaders,
body: JSON.stringify({
"name": "string",
"top_id": "string",
"bottom_id": "string",
"shoes_id": "string",
"accessories_id": "string"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()
js
const url = 'https://api.unionavatars.com/v2/outfits/assemble'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const gen_api_key = () => {
const res = fetch(url, {
method: 'POST',
heders: myHeaders,
body: JSON.stringify({
"name": "string",
"top_id": "string",
"bottom_id": "string",
"shoes_id": "string",
"accessories_id": "string"
})
})
.then(res => res.json())
.then(res => console.log(res))
}
getBodies()

Creating Avatars

Generate head

When creating an avatar, you have to provide an outfit and a head. The head is created from a 2D selfie image.

Image as a Base64 string

The accepted input format for the 2D selfie is a base 64 image. We support the most used image file extensions (jpg, png, jpeg,...).

Here's an example implementation to convert a local image to a Base64 string:

js
function readFileAsDataURI(e) {
var file = e.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
return reader.readAsDataURL(file);
}
// In this example content comes from input in UI where user loads an image.
// But you can use a BLOB class whenever it comes instead.
document.getElementById('file-input').addEventListener('change', readSingleFile, false);
js
function readFileAsDataURI(e) {
var file = e.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
return reader.readAsDataURL(file);
}
// In this example content comes from input in UI where user loads an image.
// But you can use a BLOB class whenever it comes instead.
document.getElementById('file-input').addEventListener('change', readSingleFile, false);

Head creation request

Once you have your base64 selfie ready, just send a POST request to /heads endpoint.

An example of how to perform this request:

Use a hair

Give your head a hairstyle by adding the parameter "hair_id"

js
const url = 'https://api.unionavatars.com/v2/heads'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const createHead = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
'name': 'string',
'selfie_img': 'string (base64)',
'hair_id': 'string'
})
})
.then(res => res.json())
.then(res => console.log(res))
}
createHead()
js
const url = 'https://api.unionavatars.com/v2/heads'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const createHead = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
'name': 'string',
'selfie_img': 'string (base64)',
'hair_id': 'string'
})
})
.then(res => res.json())
.then(res => console.log(res))
}
createHead()

The value of field "id" from the response is the value you have to store to use in the following request.

When you create a head, its stored for you so you can use the same head with different outfits.

Create avatar request payload

You only need three values to create a new avatar: A name, a selfie image or a head ID and an outfit ID.

  • The name field in the request is a descriptive string that helps you to identify your avatar when getting the list of them.

  • The image field (named "img") is a base64 string type. If you want to try you can use online tools.

  • The outfit ID field is a UUID string that you obtained from the available assets endpoint.

Use a Head ID instead of an image

We recommend avoid sending "img" field and send a head_id that you created in the step above. The head_id value is a UUID string.

{ "name": "<YOUR_AMAZING_AVATAR_NAME>", "head_id": "<HEAD_UUID>", "outfit_id": "<OUTFIT_UUID>", "output_format": "fbx | glb" }
{ "name": "<YOUR_AMAZING_AVATAR_NAME>", "head_id": "<HEAD_UUID>", "outfit_id": "<OUTFIT_UUID>", "output_format": "fbx | glb" }
You can skip "output_format"!

The default output format is "glb", so if you want that format you just not provide the field in the request's payload. For more information about the request's payload model to create avatar, you can check detailed documentation of the endpoint

Send request to create avatar

If you have followed the previous steps, you are ready to create your first avatar. It's as simple as sending a POST request to /avatars.

Here is an example implementation:

js
const url = 'https://api.unionavatars.com/v2/avatars'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const createAvatar = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
'name': '<YOUR_AMAZING_AVATAR_NAME>',
'head_id': '<HEAD_UUID>',
'outfit_id': '<OUTFIT_UUID>',
'output_format': 'fbx | glb'
})
})
.then(res => res.json())
.then(res => console.log(res))
}
createAvatar()
js
const url = 'https://api.unionavatars.com/v2/avatars'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const createAvatar = () => {
const res = fetch(url, {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
'name': '<YOUR_AMAZING_AVATAR_NAME>',
'head_id': '<HEAD_UUID>',
'outfit_id': '<OUTFIT_UUID>',
'output_format': 'fbx | glb'
})
})
.then(res => res.json())
.then(res => console.log(res))
}
createAvatar()

This request will return you the avatar object containing fields like "id" and "url". You can obtain this avatar in the future with its ID or do other operations on it.

The url provides you direct access to your 3D avatar file. With a GET request, you can download your avatar ready to use in games, any other platforms!

If you need more details regarding these fields, you can check the documentation of the endpoint

Notes

Timeout when creating avatar

You might face a timeout upon your request to create an avatar. This event is due to a long line on the request. Usually, if the request starts and you lose the connection, the avatar creation process might resolve your request.

In case of this situation, you can check your last avatar generated has the same name.

To get your last avatar you need to make a GET request to /avatars/last endpoint.

js
const url = 'https://api.unionavatars.com/v2/avatars/last'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const getLastAvatar = () => {
const res = fetch(url, {
headers: myHeaders,
})
.then(res => res.json())
.then(res => console.log(res))
}
getLastAvatar()
js
const url = 'https://api.unionavatars.com/v2/avatars/last'
const myHeaders = new Headers()
myHeaders.append('Authorization', 'Bearer <ACCESS_TOKEN>')
myHeaders.append('Content-Type', 'application/json')
const getLastAvatar = () => {
const res = fetch(url, {
headers: myHeaders,
})
.then(res => res.json())
.then(res => console.log(res))
}
getLastAvatar()

Troubleshooting

General problems

I have created avatars in my account but I'm not seeing them (in SDK or your own implementation)

As explained in the authentication section, avatars always belong to an organization. When you use our website to generate avatars, those avatars belong to the Union Avatars organization, therefore if you login using a different organization you won't be able to see them.

So, when you create avatars, make sure to do it from you organization. Either using our Unity SDK or by requesting it to the API.

Authentication problems

When you are making a request to our API and you are receiving a 401 or 403 you are having troubles with authentication you provided.

Could not validate credentials

If you are getting an 401 response with a body

{ "detail": "Could not validate credentials" }
{ "detail": "Could not validate credentials" }

There are many reasons causing this response:

  • You are sending correct request, but your token expired. In that case, you can create a new token as explained in login section

  • Your token is not valid. You are sending a request containing an Authorization header with the correct format, but your token value is not the same as you generated when you logged in. Maybe you changed the characters in the string or added/removed the values (like \n if you are making copy-paste).

Not autheticated

If you are getting an 401 response with a body

{ "detail": "Not authenticated" }
{ "detail": "Not authenticated" }

You are missing the Authorization header in your request, or it is malformed. To solve this issue, make sure you send your request with an Authorization header with the correct format and valid token value.

Authorization="Bearer <ACCESS_TOKEN>"
Authorization="Bearer <ACCESS_TOKEN>"

Errors 422: request's body validations

Getting a 422 status code response means that you are trying to send a payload with one or more invalid values.

Most common cases of errors in payload are:

  • Missing required parameter
  • Provide not a valid type of data for some param. For example, providing a string in a field that expects a boolean.

If you check your request body and everything seems ok, maybe you are missing "Content-Type: application/json" header.
When you don't provide this header, the API will send you a 422 response saying you are missing all required fields.

How to read 422 response

The JSON structure from 422 responses can be quite confusing. It's gonna look similar to this:

{ "detail": [ { "loc": [ "body", "name" ], "msg": "field required", "type": "value_error.missing" }, { "loc": [ "body", "img" ], "msg": "Value is not valid base64", "type": "type_error.base64" } ] }
{ "detail": [ { "loc": [ "body", "name" ], "msg": "field required", "type": "value_error.missing" }, { "loc": [ "body", "img" ], "msg": "Value is not valid base64", "type": "type_error.base64" } ] }

You always gonna have a "detail" array containing all field validations failed.
For each validation failed you will find a "loc" array with two values. The first value is the place where parameter validation failed. In this example is in the body of the request (other values could be "param" or "path"). The second value will tell you which field are referred to. In this example we are missing "name" required field and providing a non base64 string for "img" when creating an avatar.
You also will have a "msg" and "type" strings indicating which is the specific error. "msg" field will be more human readable while "type" is the internal error type of the application (you usually gonna ignore this last field).

Contact support

We are open to any suggestion or bug report!

You also can contact us to request access to our API or to request some help.

You can contact with us by sending a mail to techsupport@unionavatars.com.

Authentication


Security Scheme Type:oauth2
OAuth Flow (password):

Token URL: login

Scopes: