Skip to content

Custom Metadata

The MASV API allows team admins to create and manage custom metadata forms on portals. When a portal has a form associated with it, a response to that form called "Form Data" is required before a portal package can be created.

Note

This feature is only available for a limited number of customers. To request custom metadata API access for your team, please contact team@masv.io.

Delivery Formats

Metadata can be delivered in file format and in package upload notification emails.

The following delivery formats are supported:

  • json
  • csv
  • xml
  • email_body

Delivery formats are set on the form and multiple formats can be selected at a time.

For formats which generate deliverables in file format, these files are placed in the root of the relevant portal package.

Custom Metadata Workflow

The following steps generalize the custom metadata workflow:

  • Team admin creates a form for a portal.
  • Team admin updates the form to set form fields.
  • User creates a response to this form.
  • User creates a package, providing the form response in the create request.
  • User completes the upload flow.
  • When the user finalizes the package, the metadata for this package is delivered.

Creating a Form

Authorized users can create custom metadata forms under any portal they are an admin on. For more info on portals, see Portals.

Method Route
POST /v1/portals/{{ portal_id }}/form
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
Content-Type String Yes Must be application/json
BODY
Name Type Required Description
name String Yes Name of the form to create
delivery_formats String[] Yes An array of delivery formats for this form. See Delivery Formats for possible values.
form_template_id String No The ID of the form template this form was based on if it was based on a template. If no form template was used, leave empty.
fields Field[] No An optional array of fields you wish to create for this form. See Form Fields for information on fields and how they are structured.
curl -d "{ \"name\": \"$FORM_NAME\", \"delivery_formats\": [\"csv\", \"xml\"], \"form_template_id\": \"$FORM_TEMPLATE_ID\" }" \
-H "X-User-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \
-X POST https://api.massive.app/v1/portals/$PORTAL_ID/form

Where:

  • $USER_TOKEN is the auth token returned during auth request (refer to Authorization: Login section of this document)
  • $FORM_NAME is the name you want to give the new form
  • $FORM_TEMPLATE_ID is the template used to create this form, if one was used. If no template was used, leave blank or omit.
  • $PORTAL_ID is the ID of the portal on which you are creating this form.
    {
        "created_at": "2022-02-04T16:51:06.481Z",
        "delivery_formats": [
            "csv",
            "xml"
        ],
        "fields": [],
        "id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
        "name": "Test Form",
        "disabled": false,
        "owner_id": "portal-01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
        "team_id": "01FTVJSKRAGV1MBV2PSF0GHVVP",
        "updated_at": "2022-02-04T16:51:06.481Z"
    }

Form Fields

Form fields have the following properties:

Property Type Description
name String The name of this field. Must be unique for this form. This field is not shown to users.
label String The label which will be shown to users
type Enum The input type of this field. Possible values: checkbox radio dropdown date short_text long_text number url email package_name package_description sender_email
visibility Enum The visibility of this field. Possible values: required optional readonly hidden
default_value String The default value of this field.
position Integer The position in which this field will be rendered relative to other fields. Fields are ordered in ascending order based on this property.
options String[] A list of options for use by external frontend applications. If options are provided, default_value must be within the options array. Options is supported for the following field types: checkbox, radio, dropdown. If provided for any other field type, it will be ignored.

There are also the following additional fields which are system generated: id created_at updated_at form_id

Form fields are set by updating the form object.

Special Field Types

Fields of type package_name package_description and sender_email are used in the package creation process. There can only be one field of each of these types in a form.

For example, creating a package with a form response which contains a field of type package_name will be the value of that field as the new package's name.

Updating Forms

Authorized users can update forms which belong to any portal they are an admin on.

Method Route
PUT /v1/metadata/forms/{{ form_id }}
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
Content-Type String Yes Must be application/json
BODY

When updating forms, you should always pass in the full form object including any modifications you wish to make. The following table outlines fields which will be updated to match the values you provided.

Name Type Description
name String The form's name
delivery_formats String The delivery formats of this form. Possible values: json csv xml email_body
disabled Boolean If this is true, the form is disabled.
fields FormField[] An array of form fields. See the above Form Fields section for more info on form fields.
curl -d "{ \"name\": \"$NEW_NAME\", \"delivery_formats\": [$NEW_DELIVERY_METHODS], \"disabled\": false, \"fields\": $NEW_FIELD_ARRAY }" \
-H "X-User-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \
-X PUT https://api.massive.app/v1/metadata/forms/$FORM_ID
EXAMPLE
{
    "name": "Test Form",
    "delivery_formats": [
        "json", "csv", "xml", "email_body"
    ],
    "disabled": false,
    "fields": [
        {
            "name": "uploader_name",
            "label": "Name",
            "type": "short_text",
            "visibility": "required",
            "position": 1
        },
        {
            "name": "description",
            "label": "Package Description",
            "type": "package_description",
            "visibility": "optional",
            "position": 2
        },
        {
            "name": "name",
            "label": "Package Name",
            "type": "package_name",
            "visibility": "optional",
            "position": 3
        },
        {
            "name": "sender_email",
            "label": "Sender Email",
            "type": "sender_email",
            "visibility": "optional",
            "position": 4
        }
    ]
}
{
    "created_at": "2022-02-04T16:51:06.481Z",
    "delivery_formats": [
        "json",
        "csv",
        "xml",
        "email_body"
    ],
    "fields": [
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGC7PQJ509K49R8RTZ",
            "label": "Sender Email",
            "name": "sender_email",
            "position": 4,
            "type": "sender_email",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XG2Y5WPTPKXDY5V1CD",
            "label": "Name",
            "name": "uploader_name",
            "position": 1,
            "type": "short_text",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "required"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGEAJY2NBH57MWTG55",
            "label": "Package Description",
            "name": "description",
            "position": 2,
            "type": "package_description",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGF0M0DQ26R5MZFBVE",
            "label": "Package Name",
            "name": "name",
            "position": 3,
            "type": "package_name",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        }
    ],
    "id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
    "name": "Test Form",
    "owner_id": "portal-01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
    "team_id": "01FTVJSKRAGV1MBV2PSF0GHVVP",
    "updated_at": "2022-02-04T19:07:09.101Z"
}

Setting Form Fields

To set a form's fields, you use the Update Form endpoint described in the above section Updating Forms and provide the form's new set of fields under the fields bode property.

Warning

When a form's fields are updated, the old fields are fully replaced.

Submitting a Form Response

When submitting a form response, the only validation performed is on required fields. If a required field is missing a value in the request body, an error will be returned. Any data you pass in will be recorded as it is provided.

Authorized users with permission to create portal packages can create responses for a portal's current form.

Method Route
POST /v1/portals/{{ portal_id }}/forms/responses
HEADERS
Name Type Required Description
X-User-Token String * User JSON Web Token
X-Access-Code String * The portal's access code
Content-Type String Yes Must be application/json

Either X-User-Token or X-Access-Code is required

BODY

The body consists of a JSON object containing key/value pairs for each field. The key is the form's name, the value is an object containing a "value" property. The value of the "value" property should be the data you're submitting in string form. See the example request body below.

curl -d "{ \"$KEY1\": { \"value\": \"$VALUE1\" }, OTHER_PAIRS... }" \
-H "X-User-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \
-X POST https://api.massive.app/v1/portals/$PORTAL_ID/form/responses
EXAMPLE
{
    "uploader_name": {
        "value": "Example uploader name"
    },
    "description": {
        "value": "Example package description"
    },
    "name": {
        "value": "Example package name"
    },
    "sender_email": {
        "value": "[email protected]"
    }
}
{
    "created_at": "2022-02-04T19:33:33.623Z",
    "delivery_formats": [
        "json",
        "csv",
        "xml",
        "email_body"
    ],
    "fields": [
        {
            "created_at": "2022-02-04T19:33:33.625Z",
            "field_id": "01FV3244XGEAJY2NBH57MWTG55",
            "form_data_id": "01FV33MG9Q56YJG1J74GPS3KD2",
            "id": "01FV33MG9SB9KKDZY4H397ERJ6",
            "label": "Package Description",
            "name": "description",
            "position": 2,
            "type": "package_description",
            "updated_at": "2022-02-04T19:33:33.625Z",
            "value": "Example package description",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:33:33.625Z",
            "field_id": "01FV3244XGF0M0DQ26R5MZFBVE",
            "form_data_id": "01FV33MG9Q56YJG1J74GPS3KD2",
            "id": "01FV33MG9SY17TVHZN0QH1P0F9",
            "label": "Package Name",
            "name": "name",
            "position": 3,
            "type": "package_name",
            "updated_at": "2022-02-04T19:33:33.625Z",
            "value": "Example package name",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:33:33.625Z",
            "field_id": "01FV3244XGC7PQJ509K49R8RTZ",
            "form_data_id": "01FV33MG9Q56YJG1J74GPS3KD2",
            "id": "01FV33MG9S37XH4HJ4AARWFG7K",
            "label": "Sender Email",
            "name": "sender_email",
            "position": 4,
            "type": "sender_email",
            "updated_at": "2022-02-04T19:33:33.625Z",
            "value": "[email protected]",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:33:33.625Z",
            "field_id": "01FV3244XG2Y5WPTPKXDY5V1CD",
            "form_data_id": "01FV33MG9Q56YJG1J74GPS3KD2",
            "id": "01FV33MG9SJCG9VQ7B2ZMJRY6Z",
            "label": "Name",
            "name": "uploader_name",
            "position": 1,
            "type": "short_text",
            "updated_at": "2022-02-04T19:33:33.625Z",
            "value": "Example uploader name",
            "visibility": "required"
        }
    ],
    "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
    "id": "01FV33MG9Q56YJG1J74GPS3KD2",
    "name": "Test Form",
    "owner_id": "portal-01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
    "package_id": "placeholder",
    "team_id": "01FTVJSKRAGV1MBV2PSF0GHVVP",
    "updated_at": "2022-02-04T19:33:33.623Z"
}

Using Form Responses

To attach a form response to a new portal package, add the form response's ID to the create portal package body under the key form_data_id. This will bind a form response to the new package. Additionally, the values of any special fields will be used in the package creation process.

To see how to create a portal package, see Create a team/portal package.

Getting Package Metadata

Authorized users with a full-access package token can fetch a package's custom metadata.

Method Route
GET /v1/packages/{{ package_id }}/metadata

Info

To get a full access package token, use the List Portal Packages endpoint with new=1, and use the resulting access_token of the target package as the package token in this request.

HEADERS
Name Type Required Description
X-Package-Token String * Full-Access package JSON Web Token
curl -H "X-Package-Token: $PACKAGE_TOKEN" \
-X GET https://api.massive.app/v1/packages/$PACKAGE_ID/metadata
EXAMPLE
{
    "created_at": "2022-02-04T18:59:16.232Z",
    "delivery_formats": [
        "json",
        "csv",
        "xml",
        "email_body"
    ],
    "fields": [
        {
            "created_at": "2022-02-04T18:59:16.234Z",
            "field_id": "01FV304N2S8TGWZ43F6N44J9DZ",
            "form_data_id": "01FV31NQ486PPGJE0JDVBZE6PR",
            "id": "01FV31NQ4A3HWWQXC36ARCHWXM",
            "label": "Name",
            "name": "uploader_name",
            "position": 1,
            "type": "short_text",
            "updated_at": "2022-02-04T13:59:16.235Z",
            "value": "username",
            "visibility": "required"
        },
        {
            "created_at": "2022-02-04T18:59:16.234Z",
            "field_id": "01FV304N2S8AJ8NVVKMSCE5Y20",
            "form_data_id": "01FV31NQ486PPGJE0JDVBZE6PR",
            "id": "01FV31NQ4A93CKE6ZN2F11RRJC",
            "label": "Package Description",
            "name": "description",
            "position": 2,
            "type": "package_description",
            "updated_at": "2022-02-04T13:59:16.234Z",
            "value": "Example package description",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T18:59:16.234Z",
            "field_id": "01FV304N2S0CM38P0ATT27Q5BH",
            "form_data_id": "01FV31NQ486PPGJE0JDVBZE6PR",
            "id": "01FV31NQ4AW20WPJHGEVFETV5C",
            "label": "Package Name",
            "name": "name",
            "position": 3,
            "type": "package_name",
            "updated_at": "2022-02-04T13:59:16.234Z",
            "value": "Example package name",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T18:59:16.234Z",
            "field_id": "01FV304N2S4TQGVSW5HWT7QD0X",
            "form_data_id": "01FV31NQ486PPGJE0JDVBZE6PR",
            "id": "01FV31NQ4A9Q5RMYBY5DBMJPTE",
            "label": "Sender Email",
            "name": "sender_email",
            "position": 4,
            "type": "sender_email",
            "updated_at": "2022-02-04T13:59:16.235Z",
            "value": "[email protected]",
            "visibility": "optional"
        }
    ],
    "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
    "id": "01FV31NQ486PPGJE0JDVBZE6PR",
    "name": "Test Form",
    "owner_id": "portal-01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
    "package_id": "01FV31NS5J98H69K9JT2G8QP33",
    "team_id": "01FTVJSKRAGV1MBV2PSF0GHVVP",
    "updated_at": "2022-02-04T13:59:18.324Z"
}

Getting Portal Metadata Fields

To get the fields required to create a portal form response, you use the Get Portal endpoint. If it has a form requirement, an array of form fields will be returned.

Authorized users with a full-access package token can fetch a portal's details, including metadata fields.

Metadata fields are returned in array form under custom_metadata and are sorted ascendingly by their position field.

Method Route
GET /v1/portals/{{ portal_id }}
HEADERS
Name Type Required Description
X-User-Token String * User JSON Web Token
X-Access-Code String * A portal's access code

Either X-User-Token or X-Access-Code are required.

curl -H "X-User-Token: $USER_TOKEN" \
-X GET https://api.massive.app/v1/portals/$PORTAL_ID
EXAMPLE
{
    "active": true,
    "cloud_connections": [],
    "created_at": "2022-02-04T16:51:02.226Z",
    "custom_metadata": [
        {
            "label": "Sender Email",
            "name": "sender_email",
            "position": 4,
            "type": "sender_email",
            "visibility": "optional"
        },
        {
            "label": "Package Name",
            "name": "name",
            "position": 3,
            "type": "package_name",
            "visibility": "optional"
        },
        {
            "label": "Package Description",
            "name": "description",
            "position": 2,
            "type": "package_description",
            "visibility": "optional"
        },
        {
            "label": "Name",
            "name": "uploader_name",
            "position": 1,
            "type": "short_text",
            "visibility": "required"
        }
    ],
    "custom_webhooks": [],
    "disable_upload_receipt": false,
    "has_access_code": false,
    "has_download_password": false,
    "id": "01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
    "name": "Example portal",
    "primary_color": "#ABCABC",
    "recipients": null,
    "subdomain": "portalsubdomain",
    "updated_at": "2022-02-04T11:51:02.226Z"
}

Deleting Forms

Authorized users can delete custom metadata forms.

Method Route
DELETE /v1/metadata/forms/{{ form_id }}
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
BODY

No body.

curl -H "X-User-Token: $USER_TOKEN" \
-X DELETE https://api.massive.app/v1/metadata/forms/$FORM_ID
RESPONSE

Status Code 204: No Content

Creating a Form Template

Authorized users can create custom metadata form templates for their team.

Form Templates almost directly mirror Forms.

Method Route
POST /v1/teams/{{ team_id }}/forms/templates
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
Content-Type String Yes Must be application/json
BODY
Name Type Required Description
name String Yes Name of the form to create
delivery_formats String[] Yes An array of delivery formats for this form. See Delivery Formats for possible values.
curl -d "{ \"name\": \"$FORM_TEMPLATE_NAME\", \"delivery_formats\": [\"csv\", \"xml\"] }" \
-H "X-User-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \
-X POST https://api.massive.app/v1/teams/$TEAM_ID/forms/templates

Where:

  • $USER_TOKEN is the auth token returned during auth request (refer to Authorization: Login section of this document)
  • $FORM_TEMPLATE_NAME is the name you want to give the new form
  • $TEAM_ID is the ID of the team on which you are creating this form template.
    {
    "created_at": "2022-01-25T19:12:28.423Z",
    "delivery_formats": [
        "csv",
        "xml"
    ],
    "id": "01FT9AEPR7YCAF0MTR6SC5ETRH",
    "name": "Test Template",
    "team_id": "01FT994WS8BAGDNQFS627Q69R6",
    "updated_at": "2022-01-25T19:12:28.423Z"
}

Updating Form Templates

Authorized users can update form templates which belong to their team.

Method Route
PUT /v1/metadata/forms/templates/{{ form_template_id }}
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
Content-Type String Yes Must be application/json
BODY

When updating form templates, you should always pass in the full form template object including any modifications you wish to make. The following table outlines fields which will be updated to match the values you provided.

Name Type Description
name String The form's name
delivery_formats String The delivery formats of this form. Possible values: json csv xml email_body
fields FormField[] An array of form fields. See the above Form Fields section for more info on form fields.
curl -d "{ \"name\": \"$NEW_NAME", \"delivery_formats\": $NEW_DELIVERY_METHOD_ARRAY, \"disabled\": false, \"fields\": $NEW_FIELD_ARRAY }" \
-H "X-User-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \
-X PUT https://api.massive.app/v1/metadata/forms/templates/$FORM_TEMPLATE_ID
EXAMPLE
{
    "name": "Test Form Template",
    "delivery_formats": [
        "json", "csv", "xml", "email_body"
    ],
    "fields": [
        {
            "name": "uploader_name",
            "label": "Name",
            "type": "short_text",
            "visibility": "required",
            "position": 1
        },
        {
            "name": "description",
            "label": "Package Description",
            "type": "package_description",
            "visibility": "optional",
            "position": 2
        },
        {
            "name": "name",
            "label": "Package Name",
            "type": "package_name",
            "visibility": "optional",
            "position": 3
        },
        {
            "name": "sender_email",
            "label": "Sender Email",
            "type": "sender_email",
            "visibility": "optional",
            "position": 4
        }
    ]
}
{
    "created_at": "2022-02-04T16:51:06.481Z",
    "delivery_formats": [
        "json",
        "csv",
        "xml",
        "email_body"
    ],
    "fields": [
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGC7PQJ509K49R8RTZ",
            "label": "Sender Email",
            "name": "sender_email",
            "position": 4,
            "type": "sender_email",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XG2Y5WPTPKXDY5V1CD",
            "label": "Name",
            "name": "uploader_name",
            "position": 1,
            "type": "short_text",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "required"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGEAJY2NBH57MWTG55",
            "label": "Package Description",
            "name": "description",
            "position": 2,
            "type": "package_description",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        },
        {
            "created_at": "2022-02-04T19:07:09.104Z",
            "form_id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
            "id": "01FV3244XGF0M0DQ26R5MZFBVE",
            "label": "Package Name",
            "name": "name",
            "position": 3,
            "type": "package_name",
            "updated_at": "2022-02-04T19:07:09.104Z",
            "visibility": "optional"
        }
    ],
    "id": "01FV2TB1KHRFQJ76MEWPKDX2G9",
    "name": "Test Form Template",
    "owner_id": "portal-01FV2TAXEJ7DVRX2WQ0W5Y4QA0",
    "team_id": "01FTVJSKRAGV1MBV2PSF0GHVVP",
    "updated_at": "2022-02-04T19:07:09.101Z"
}

Deleting Form Templates

Authorized users can delete custom metadata form templates.

Method Route
DELETE /v1/metadata/forms/templates/{{ form_template_id }}
HEADERS
Name Type Required Description
X-User-Token String Yes User JSON Web Token
BODY

No body.

curl -H "X-User-Token: $USER_TOKEN" \
-X DELETE https://api.massive.app/v1/metadata/forms/templates/$FORM_TEMPLATE_ID
RESPONSE

Status Code 204: No Content