Skip to main content
PUT
Upsert group attributions bulk

Asynchronous upsert

This endpoint does not apply your payload during the request: it stores it and creates an import that applies it in the background. The response gives you the import_id of that import, and the number of items your request contained.
A 200 therefore means the import was created, not the payload was applied. To know how it went, fetch the import with the Fetch import route until its status is finished, then read its error flag:
  • error: false — every item of your payload has been upserted.
  • error: true — read title in data_tables_details[].error to know what happened. ValidationError means the payload was refused and nothing was upserted, description listing the invalid items. PartialFailure means part of it was applied: description counts the items that reported an issue, and parsing_error_details names the skipped ones — the most recent 100 — each with its line_number, row and details.
Imports of a company run one after the other, so an import can stay scheduled for a while when another one is already running. A 400 is still returned during the request itself, for a malformed body or a payload above the limit — in that case no import is created.

Merging successive calls with debounce

A payload above the limit of 200 has to be split across several calls, and each call would otherwise create its own import — all queued behind one another. Pass debounce, a number of seconds, to hold the import open: every call to the same endpoint made during that window joins the same import instead of queuing a new one, and they all return the same import_id. The window is opened by the first call, and a later call joins it without pushing its start further. Each payload keeps its own validation. A refused payload upserts nothing, but the payloads merged beside it are still applied — the import then reports the reason of every refusal in data_tables_details[].error. Only calls to the same endpoint are merged: users, manager attributions and group attributions always get their own import. This is deliberate, since attributions need the users they reference to exist already — send your users first, wait for their import to finish, then send the attributions.

Behavior

  • Transaction: If one group attribution is not parsable, none of the attributions of your call are upserted and the import finishes in error. You have to fix your payload and send it to us again. And if the import finishes without error, it means that every group attribution you sent us have been upserted. This all-or-nothing applies to the payload of your own call: when several calls share an import through debounce, a refused payload does not prevent the others from being applied
  • Conflict Rule and upsert: Be careful, each user can only have one group by dimension for a given period. Given new attributions dates will override conflicting dates already present in Qobra. Also, if you send a payload with two groups attributions for the same user over the same period the import is refused.
  • Limit: you can’t update more than 200 group attributions at a time.
  • Error behavior: In case of any error, your group attributions wont be upserted

Authorizations

X-API-Key
string
header
required

Query Parameters

debounce
integer
default:0

Optional (minimum: 0): debounce is the number of seconds we wait before starting the import. Every call to this endpoint made during that window joins the same import instead of queuing a new one, and they all return the same import_id. Use it when a payload above the limit of 200 has to be split across several calls. Only calls to this same endpoint are merged: users, manager attributions and group attributions always get their own import.

Body

application/json

The body contains the user data necessary to create a new user in Qobra

data
GroupAttributionPutBodyModel · object[]
required

Response

Import created

The upsert is performed as a background import: the response identifies the import you just created, not the upserted objects. Fetch the import to know how it went.

import_id
string<ObjectId>
required

unique identifier of the import you created

objects_imported
integer
required

number of items your request contained