Method POST/partner-portal /interventions
Record an intervention on a product from a repairer or recycler partner account. Partner session, no API key.
On this page
You record an intervention that you have just carried out on a product: a repair, a servicing, a reconditioning, a recycling. The intervention is added to the history of the product, carries your name and states what you proved at the moment of recording it.
The full address is
https://api.sealtrust.io/v1/partner-portal/interventions. The same route
exists without the /v1 prefix, and the /v1 form is the one recommended for
a new integration.
The partner portal is a different surface from the key-authenticated API. It authenticates with the session of a partner account, and an API key gives no access to it.
This call is not replayable. Two identical calls create two interventions. No idempotency header is read by this endpoint.
#
Session of a partner account, of repairer or recycler type. The session token
is the one returned by POST /v1/auth/login, in the access_token field.
Authorization: Bearer <votre jeton de session>The access_token session cookie is accepted as well. It is the form that the
browser uses. It triggers the origin and anti-forgery token checks described
below.
Call this endpoint from your server, with the Authorization header. A call
issued by a browser page goes through additional origin and request forgery
checks, which return a 403 when they are not satisfied.
Four conditions must be met for an intervention to be recorded.
- The account is of repairer or recycler type. Otherwise the response is a 403.
- The account has at least one active accreditation. Otherwise the response is
a 403 carrying the message
Aucune accréditation active. - The product belongs to a brand that has accredited this account. Otherwise the response is a 403 or a 404.
- The intervention type is covered by your accreditations on the brand of this product. Otherwise the response is a 422 that lists the allowed types.
Accreditations are granted by the brand, brand by brand. One same account can hold both types on one same brand, and the allowed intervention types are then the union of the two sets.
| Accreditation | Allowed intervention types |
|---|---|
| Repairer | repair, maintenance, reconditioning, after_sale_service |
| Recycler | recycling, end_of_life, destruction, return |
The GET /v1/partner-portal/products/{identifier} endpoint returns the
allowed_event_types list computed for the product concerned, which saves you
from guessing.
#Call limit
A call limit applies to this endpoint. It is set for the normal use of the portal, where you look for a product then record an intervention.
Beyond it, the API replies 429. The refusal carries a Retry-After header that
gives the number of seconds to wait. Wait that delay, then call again.
The limit covers the whole partner portal. Alternating between the endpoints therefore gives you no margin back. Space out your calls instead of sending them in bursts.
The value of the limit is not a commitment and can change without notice. Do
not hard-code any threshold in your code, rely on Retry-After.
There is neither a daily quota nor a per brand counter here: these two mechanisms are attached to API keys, and the partner portal uses none.
#Path and query parameters
This endpoint has no path parameter and no query parameter. Everything goes through the request body.
#Request body
application/json format. Any field absent from this table gets the request
refused with a 422.
| Name | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | The product on which you intervened. Edge spaces are removed. An empty value is refused. Four forms are accepted, see below. |
event_type | string | yes | The intervention type. The value is stripped of its edge spaces and lowercased before checking. It must appear among the types allowed by your accreditations on the brand of the product. |
title | string | yes | Short title of the intervention. 255 characters at most. Edge spaces are removed. An empty value is refused. |
description | string | no | Free text. No maximum length. Recorded as it is. |
metadata | object | no | Your own information about the intervention. Recorded as it is. The partner_type key is added to it if you do not provide it. |
proof_code | string | no | The handover code read by the customer, or the work order issued by the brand. Spaces and hyphens are removed, the value is uppercased. An empty string counts as no code. |
#The four accepted forms for identifier
They are tried in this order, and the search is bounded to the brands that have accredited you.
| Form | Example | Recognized by |
|---|---|---|
| Label fingerprint | 0x0000000000000000000000000000000000000000000000000000000000000000 | starts with 0x |
| Token identifier | 10000000000000000000000000000000000000000000000000000000000000000000000000000 | contains only digits |
| Certificate number | CERT-EXEMPLE-0001 | matches a certificate of the brand |
| Serial number printed on the product | 000000000000 | 12 characters of the Crockford Base32 alphabet |
The token identifier has 77 to 78 digits. It is stored and returned as a string of characters. Declare it as a string in your integration, and size the field accordingly.
The serial number tolerates the common reading confusions: the letters I and
L are read as the digit 1, the letter O as the digit 0, and case does
not matter. It is the form to favor when you have the object in hand, because
it is the only one printed on it. A destroyed or withdrawn product is never
resolved.
#The proof level, and how to raise it
An accreditation says that you have the right to work on the products of a
brand. It does not say that this precise product passed through your hands, and
the identifier is printed on the object. The proof_level field of the
response therefore records what you actually proved.
proof_level | What you sent | What it is worth |
|---|---|---|
declared | no proof_code | you declared the intervention and you knew the identifier |
customer_code | a handover code generated by the end customer | the holder of the product handed it to you |
work_order | a work order issued by the brand | the brand entrusted this precise product to you |
The end customer generates their handover code from their account, through
POST /v1/custody/repair-codes. The code is 8 characters long and is displayed
only once. It is valid for a single product, is used only once, and expires
after 30 days by default, a duration that the issuer can set between 1 and 365
days. The work order is issued by the brand from its console, and it names both
the product and your account.
A refused code cancels the whole call, and nothing is recorded. If the code
does not go through, check it with the customer, or record the intervention
without proof_code, at the declared level.
#Example request
curl -i -X POST https://api.sealtrust.io/v1/partner-portal/interventions \
-H "Authorization: Bearer VOTRE_JETON_DE_SESSION" \
-H "Content-Type: application/json" \
-d '{
"identifier": "000000000000",
"event_type": "repair",
"title": "Remplacement de la fermeture éclair",
"description": "Ancienne fermeture remplacée par une pièce du fabricant.",
"metadata": {
"duree_minutes": 45,
"pieces": ["fermeture éclair"]
},
"proof_code": "23456789"
}'const response = await fetch(
"https://api.sealtrust.io/v1/partner-portal/interventions",
{
method: "POST",
headers: {
Authorization: "Bearer VOTRE_JETON_DE_SESSION",
"Content-Type": "application/json",
},
body: JSON.stringify({
identifier: "000000000000",
event_type: "repair",
title: "Remplacement de la fermeture éclair",
description: "Ancienne fermeture remplacée par une pièce du fabricant.",
metadata: {
duree_minutes: 45,
pieces: ["fermeture éclair"],
},
proof_code: "23456789",
}),
},
);
console.log(response.status);
console.log(await response.json());import requests
response = requests.post(
"https://api.sealtrust.io/v1/partner-portal/interventions",
headers={
"Authorization": "Bearer VOTRE_JETON_DE_SESSION",
"Content-Type": "application/json",
},
json={
"identifier": "000000000000",
"event_type": "repair",
"title": "Remplacement de la fermeture éclair",
"description": "Ancienne fermeture remplacée par une pièce du fabricant.",
"metadata": {
"duree_minutes": 45,
"pieces": ["fermeture éclair"],
},
"proof_code": "23456789",
},
timeout=30,
)
print(response.status_code)
print(response.json())#Example response
HTTP code 201.
{
"id": 8123,
"product_id": 4096,
"brand_id": 12,
"event_type": "repair",
"proof_level": "customer_code",
"title": "Remplacement de la fermeture éclair",
"description": "Ancienne fermeture remplacée par une pièce du fabricant.",
"event_metadata": {
"duree_minutes": 45,
"pieces": ["fermeture éclair"],
"partner_type": "repairer"
},
"performed_by": "Atelier Exemple (réparateur accrédité)",
"product_name": "Sac de voyage Exemple SAS",
"occurred_at": "2026-08-20T14:32:07.512430+00:00",
"created_at": "2026-08-20T14:32:07.512430+00:00"
}The twelve fields of the response.
| Field | Type | Description |
|---|---|---|
id | integer | Identifier of the intervention, assigned in order of creation. Do not expose it publicly. |
product_id | integer | Identifier of the product resolved from identifier. |
brand_id | integer | Identifier of the brand of the product. |
event_type | string | The intervention type recorded, in lowercase. |
proof_level | string or null | declared, customer_code or work_order. See the table above. |
title | string | The title, stripped of its edge spaces. |
description | string or null | The description, as you sent it. |
event_metadata | object or null | What you sent in metadata, augmented with the partner_type key. |
performed_by | string or null | Your identity, as it will appear in the history of the product. |
product_name | string or null | Name of the product as it is recorded. |
occurred_at | string | Date and time of the intervention, in ISO 8601 format with time zone. |
created_at | string | Date and time of the recording, in ISO 8601 format with time zone. |
#What performed_by contains
This field is built from your account, followed by the capacity in which you
intervened, for example réparateur accrédité. The value retained is your
first name and your last name, failing that the name of your company, failing
that the email address of the account. Fill in your name or your company in
your profile if you do not want your email address to appear in the history of
the products.
#What partner_type contains
The partner_type key is added to metadata when you do not provide it. It is
repairer for the four repair intervention types, and recycler for the four
end-of-life types. If you send this key yourself, your value is kept.
#Errors
| Code | Condition | What to do |
|---|---|---|
| 401 | Neither an Authorization header nor an access_token session cookie. Message Not authenticated, with the WWW-Authenticate: Bearer header. | Add the Authorization: Bearer <votre jeton de session> header. |
| 401 | Token unreadable, expired or badly signed. Message Invalid JWT token. | Sign in again through POST /v1/auth/login and take the token it returns. |
| 401 | Token revoked by a sign-out or a password change. Message Token has been revoked. | Sign in again. |
| 401 | Token issued for something other than a session, for example an address confirmation. Message Invalid token. A token waiting for a second factor gives MFA verification required. | Finish the sign-in and use the session token it returns. |
| 401 | The token is signed but names no account. Message Invalid token: missing email. | Sign in again through POST /v1/auth/login and take the token it returns. |
| 401 | Account disabled. Message Account disabled. | Contact the brand that accredited you. Trying again will change nothing. |
| 403 | The account is neither a repairer nor a recycler. Message Partner account required (repairer or recycler). | Use the partner account that the brand created for you. |
| 403 | The account has no active accreditation. Message Aucune accréditation active. | Ask the brand to accredit you, or to reactivate your accreditation. |
| 403 | The product is not within the scope of your accreditation. Message Ce produit appartient à une marque qui ne vous a pas accrédité. | This product is not within your scope. Ask this brand for an accreditation. |
| 403 | The call comes from a browser, from an origin that we do not allow, or without stating its origin. Messages Forbidden origin and Origin or Referer header required. | Call this endpoint from your server, with the Authorization header. |
| 403 | The call comes from a browser and the anti-forgery token is missing or does not match. Message bad_csrf. | Call this endpoint from your server, with the Authorization header. |
| 404 | No accessible product matches identifier. Message Produit introuvable. | Check the identifier and its form. A destroyed or withdrawn product replies the same thing. |
| 404 | The account named by the token no longer exists. Message User not found. | The account has been deleted. Contact the brand that accredited you. |
| 422 | Invalid body: required field absent, unknown field, identifier, event_type or title empty. | The body of the response lists the fields at fault and the reason for each refusal. Correct and call again. |
| 422 | The title exceeds 255 characters. The body of the response does not name the field at fault. | Shorten the title and put the detail in description, which has no maximum length. |
| 422 | The intervention type is covered by none of your accreditations on this brand. The message lists the allowed types. | Choose a type from the returned list. If none suits, ask the brand for the corresponding accreditation. |
| 422 | The proof_code matches no code issued for this product. Message Code inconnu pour ce produit. | Check that the code was indeed issued for this precise product. Call again without proof_code to record the intervention at the declared level. |
| 422 | The code has already been used. Message Ce code a déjà servi. | A code serves only once. Ask for a new one, or call again without proof_code. |
| 422 | The code was canceled by its issuer. Message Ce code a été annulé par son émetteur. | Ask the customer or the brand to issue a new one. |
| 422 | The code has passed its validity date. Message Ce code a expiré. | Ask for a new one. |
| 422 | The work order names a partner other than you. Message Ce bon de travail a été émis pour un autre partenaire. | This order is not intended for you. Ask the brand to issue one in your name. |
| 429 | You have exceeded the call limit. The response carries a Retry-After header. | Wait the number of seconds given by Retry-After, then call again. The limit covers the whole partner portal, so space out all of your calls. |
#See also
GET /partner-portal/interventions, list the interventions that your account has recorded.GET /partner-portal/products/{identifier}, find a product of a brand that has accredited you.GET /partner-portal/me, read your partner profile and the brands that have accredited you.
Was this page helpful?
Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.