Docs
IntegrationsGuides

Submitting a MassID

End-to-end guide for submitting a MassID — create document, add events, and close.

Use this sequence as the base implementation pattern for submitting a complete MassID lifecycle through the Carrot API.

Prerequisites

Before you begin, ensure you have:

  • A registered Network Integrator account with valid API credentials
  • Participant and address data ready — these are created inline on your first submission (no separate creation step needed)
  • Familiarity with core concepts — especially the immutable event-sourced model

Step 1: Create the document

Create the root record with classification and baseline visibility fields. Participant and address data can be sent inline as objects on the first request. On subsequent requests, you can reuse the IDs returned by the platform.

POST /v1/documents
{
  "category": "MassID",
  "type": "YOUR_WASTE_TYPE",
  "measurementUnit": "kg",
  "externalCreatedAt": "2026-03-01T10:00:00.000Z",
  "isPublic": true,
  "isPubliclySearchable": true,
  "participant": {
    "countryCode": "BR",
    "name": "Example Company",
    "taxId": "11111111111111",
    "taxIdType": "CNPJ",
    "type": "COMPANY"
  },
  "address": {
    "name": "Main Facility",
    "street": "Rua das Colinas",
    "number": "500",
    "neighborhood": "Centro",
    "city": "São Paulo",
    "countryState": "São Paulo",
    "countryCode": "BR",
    "zipCode": "08575720",
    "latitude": -23.5489,
    "longitude": -46.6388
  },
  "externalId": "your-internal-tracking-id",
  "deduplicationId": "unique-id-generated-before-first-attempt"
}
FieldRequiredDescription
categoryYesAlways MassID for mass tracking documents
typeYesWaste type — defined per methodology (see note below)
measurementUnitYeskg for recycling, kg CO₂e for carbon
externalCreatedAtYesISO 8601 timestamp of the real-world document creation
isPublicYesWhether the document is publicly visible
isPubliclySearchableYesWhether the document appears in public search
participantNo*Inline participant object (see required fields below)
participantIdNo*ID of an existing participant — use for subsequent requests
addressNo**Inline address object (see required fields below)
addressIdNo**ID of an existing address — use for subsequent requests
externalIdNoYour internal ID for reconciliation — useful for mapping back to your system
deduplicationIdNoIdempotency key — see tip below

* Send either participant (inline object) or participantId (ID), not both.

** Send either address (inline object) or addressId (ID), not both.

Inline creation vs. ID reuse

On your first request, send full participant and address objects. The platform creates them and returns their IDs in the response. On subsequent requests, reuse those IDs via participantId and addressId instead of resending the full objects.

Methodology-specific values

The type field (waste type) and measurementUnit are defined by your target methodology. See the methodology integration guides for the specific values required.

Inline participant required fields:

FieldTypeDescription
countryCodestringTwo-letter country code (ISO 3166-1 alpha-2)
namestringFull name or company name
taxIdstringTax ID number (digits only, no formatting)
taxIdTypestringTax ID type — e.g. CPF, CNPJ
typestringPERSON or COMPANY

Reference: Documents API.

Step 2: Append timeline events

Append events in chronological order to represent operational steps. Each event is immutable once created.

ACTOR events

ACTOR events register participant roles on the document timeline. Each requires a label identifying the role, plus a participant and address:

POST /v1/documents/{documentId}/events
{
  "name": "ACTOR",
  "label": "YOUR_ROLE_LABEL",
  "externalCreatedAt": "2026-03-01T10:05:00.000Z",
  "isPublic": true,
  "participant": {
    "countryCode": "BR",
    "name": "Participant Name",
    "taxId": "22222222222",
    "taxIdType": "CPF",
    "type": "PERSON"
  },
  "address": {
    "name": "Collection Site",
    "street": "Rua das Colinas",
    "number": "500",
    "neighborhood": "Centro",
    "city": "São Paulo",
    "countryState": "São Paulo",
    "countryCode": "BR",
    "zipCode": "08575720",
    "latitude": -23.5489,
    "longitude": -46.6388
  }
}

The label value (e.g. "Waste Generator", "Hauler", "Processor") is defined by each methodology. See your methodology guide for the required roles and their labels.

After the first inline creation, you can use participantId and addressId for subsequent events referencing the same participant or address.

CUSTOM events

CUSTOM events represent methodology-specific operational steps. The event name, required metadata attributes, and sequence are all defined by the methodology:

POST /v1/documents/{documentId}/events
{
  "name": "YOUR_EVENT_NAME",
  "externalCreatedAt": "2026-03-01T11:00:00.000Z",
  "isPublic": true,
  "participantId": "participant-id-from-previous-response",
  "addressId": "address-id-from-previous-response",
  "metadata": {
    "attributes": [
      { "name": "YOUR_ATTRIBUTE_NAME", "value": "attribute-value" }
    ]
  },
  "value": 150.5
}

The value field on events contributes to the document's currentValue. For example, a weighing event with value: 150.5 sets the tracked weight.

Methodology guides

Each methodology defines the specific event sequence, event names, and required metadata attributes. See the methodology integration guides for the values required by each methodology.

Inline address required fields:

FieldTypeDescription
citystringCity name
countryCodestringTwo-letter country code (ISO 3166-1 alpha-2)
countryStatestringState or province
latitudenumberLatitude coordinate
longitudenumberLongitude coordinate
namestringDescriptive name for the address
neighborhoodstringNeighborhood or district
numberstringStreet number
streetstringStreet name
zipCodestringPostal code (digits only, no formatting)

Document status lifecycle

Documents follow a strict status lifecycle:

  • OPEN — Default status after creation. Events can be appended freely.
  • CLOSE event — Transitions the document to CLOSED. After closing, only RELATED events are accepted.
  • CANCEL event — Transitions the document to CANCELLED. No further events are accepted.

Send a CLOSE event when the supply chain lifecycle is complete:

POST /v1/documents/{documentId}/events
{
  "name": "CLOSE",
  "externalCreatedAt": "2026-03-02T16:00:00.000Z",
  "isPublic": true,
  "participantId": "integrator-participant-id"
}

See Event Specification for the full list of event categories.

Reference: Events API.

For high-volume integrations, consider the batch events endpoint to submit multiple events per request.

Step 3: Attach evidence files (optional)

Some methodology rules require evidence attachments (e.g. scale tickets, transport manifests). The pattern is:

  1. Request a pre-signed upload URL via the Attachments API
  2. Upload the file directly to the pre-signed URL
  3. Reference the attachment in the relevant event's attachments array

Attachments are linked to specific events, not to the document as a whole. This ensures each piece of evidence is tied to the operational step it documents.

Reference: Attachments API.

Step 4: Retrieve and validate final state

Fetch the document and verify before considering the submission complete:

  • Event count and ordering — all expected events are present in chronological order
  • Status is CLOSED — the document has been properly closed
  • currentValue > 0 — the document has a positive tracked value
  • At least one ACTOR event — the required participant roles are registered
  • Participant and address links — all references resolve correctly
  • Metadata completeness — required attributes are present on each event per the methodology

Reference: GET document by ID.

Operational tips

deduplicationId

Always send deduplicationId on retryable write calls (document creation and event creation). Generate a unique ID before the first attempt, store it, and reuse the same ID on every retry. The ID is scoped per integrator — two different integrators can use the same ID without conflict. This guarantees at-most-once semantics: if the server received your first request but the response was lost, the retry will return the original result instead of creating a duplicate.

  • Use externalId on documents and events for reconciliation with your internal systems.
  • Treat 4xx as data/integration issues and 5xx as transient failures — see Error Handling.
  • Keep your source timestamp strategy deterministic — see Data Formats.

On this page