Change items

data.collection.mutate@1

Adds, changes, archives or deletes one row in a table this key can change. A change to an existing row names the revision you read it at, so a change made since then is never overwritten. It needs a key with Act.

Add a row

Send POST /invocations with the target this operation's catalogue entry gives: replace YOUR_FEATURE_ID with its featureId, and YOUR_TABLE_REF with a table's resourceRef from List data tables. The field ids are the table's own (fields[].id).

# A new operationId for each new request; the same one to retry it.
curl https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations \
  -H "Authorization: Bearer gl_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "featureId": "YOUR_FEATURE_ID",
    "export": "mutateCollection",
    "contractRef": "data.collection.mutate@1"
  },
  "operationId": "add-quote-request-1",
  "input": {
    "resourceRef": "YOUR_TABLE_REF",
    "mutation": {
      "kind": "create",
      "values": {
        "f_name": "Jordan Example",
        "f_email": "jordan@example.com",
        "f_details": "A two-tier cake for 40 guests"
      }
    }
  }
}'
// A new operationId for each new request; the same one to retry it.
const response = await fetch(
  "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer gl_YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "target": {
        "featureId": "YOUR_FEATURE_ID",
        "export": "mutateCollection",
        "contractRef": "data.collection.mutate@1"
      },
      "operationId": "add-quote-request-1",
      "input": {
        "resourceRef": "YOUR_TABLE_REF",
        "mutation": {
          "kind": "create",
          "values": {
            "f_name": "Jordan Example",
            "f_email": "jordan@example.com",
            "f_details": "A two-tier cake for 40 guests"
          }
        }
      }
    }),
  },
);
const receipt = await response.json();
console.log(response.status, receipt);
import requests

# A new operationId for each new request; the same one to retry it.
response = requests.post(
    "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
    headers={"Authorization": "Bearer gl_YOUR_API_KEY"},
    json={
        "target": {
            "featureId": "YOUR_FEATURE_ID",
            "export": "mutateCollection",
            "contractRef": "data.collection.mutate@1",
        },
        "operationId": "add-quote-request-1",
        "input": {
            "resourceRef": "YOUR_TABLE_REF",
            "mutation": {
                "kind": "create",
                "values": {
                    "f_name": "Jordan Example",
                    "f_email": "jordan@example.com",
                    "f_details": "A two-tier cake for 40 guests",
                },
            },
        },
    },
    timeout=30,
)
print(response.status_code, response.json())

Change a row

Copy row from the row's recordRef and expectedRevision from its revision, as Read a list or the last change's answer gives them. Only the fields in values change.

# A new operationId for each new request; the same one to retry it.
curl https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations \
  -H "Authorization: Bearer gl_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "featureId": "YOUR_FEATURE_ID",
    "export": "mutateCollection",
    "contractRef": "data.collection.mutate@1"
  },
  "operationId": "change-quote-request-1",
  "input": {
    "resourceRef": "YOUR_TABLE_REF",
    "mutation": {
      "kind": "patch",
      "row": {
        "businessProfileId": "YOUR_BUSINESS_ID",
        "featureId": "YOUR_ROW_FEATURE_ID",
        "collectionId": "YOUR_ROW_COLLECTION_ID",
        "id": "YOUR_ROW_ID"
      },
      "expectedRevision": 1,
      "values": {
        "f_phone": "555-0100"
      }
    }
  }
}'
// A new operationId for each new request; the same one to retry it.
const response = await fetch(
  "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer gl_YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "target": {
        "featureId": "YOUR_FEATURE_ID",
        "export": "mutateCollection",
        "contractRef": "data.collection.mutate@1"
      },
      "operationId": "change-quote-request-1",
      "input": {
        "resourceRef": "YOUR_TABLE_REF",
        "mutation": {
          "kind": "patch",
          "row": {
            "businessProfileId": "YOUR_BUSINESS_ID",
            "featureId": "YOUR_ROW_FEATURE_ID",
            "collectionId": "YOUR_ROW_COLLECTION_ID",
            "id": "YOUR_ROW_ID"
          },
          "expectedRevision": 1,
          "values": {
            "f_phone": "555-0100"
          }
        }
      }
    }),
  },
);
const receipt = await response.json();
console.log(response.status, receipt);
import requests

# A new operationId for each new request; the same one to retry it.
response = requests.post(
    "https://api.growlocal.site/api/v1/profiles/YOUR_BUSINESS_ID/invocations",
    headers={"Authorization": "Bearer gl_YOUR_API_KEY"},
    json={
        "target": {
            "featureId": "YOUR_FEATURE_ID",
            "export": "mutateCollection",
            "contractRef": "data.collection.mutate@1",
        },
        "operationId": "change-quote-request-1",
        "input": {
            "resourceRef": "YOUR_TABLE_REF",
            "mutation": {
                "kind": "patch",
                "row": {
                    "businessProfileId": "YOUR_BUSINESS_ID",
                    "featureId": "YOUR_ROW_FEATURE_ID",
                    "collectionId": "YOUR_ROW_COLLECTION_ID",
                    "id": "YOUR_ROW_ID",
                },
                "expectedRevision": 1,
                "values": {
                    "f_phone": "555-0100",
                },
            },
        },
    },
    timeout=30,
)
print(response.status_code, response.json())

Parameters

What goes in input:

Name Type Required Description
resourceRef string Yes The table to change: its resourceRef from List data tables.
mutation object Yes The one change to make.
mutation.kind one of create, patch, archive, unarchive, delete, restore Yes What to do: create adds a row; patch changes some of a row's values; archive and unarchive put a row away and bring it back; delete moves it to Trash, where it can be restored for 30 days; restore brings it back from Trash.
mutation.values object Sometimes Field values keyed by field id (f_…). Required for create and patch; unarchive may correct values as it restores. patch changes only the fields you send.
mutation.idempotencyKey string No create only, 1 to 128 characters: a second create with the same key in this table answers with the row the first one made instead of adding another. A table with an identity field (idempotencyFieldId in List data tables) uses that field's value as the key.
mutation.row object Sometimes The row to change, as its recordRef from Read a list. Required for every kind but create.
mutation.row.businessProfileId string Yes Your business's id.
mutation.row.featureId string Yes The featureId of the row's recordRef.
mutation.row.collectionId string Yes The collectionId of the row's recordRef.
mutation.row.id string Yes The row's id.
mutation.expectedRevision integer Sometimes The row's revision when you read it. Required for every kind but create: if the row has changed since, nothing is changed and the answer is a conflict.

Response

A call that worked answers 200 with an applied receipt; its output holds these fields, among others. GET /catalog/data.collection.mutate@1 answers the complete shape as JSON Schema.

Name Type Description
row object The row the change made or changed, as row for the next change.
row.id string The row's id.
revision integer The row's new revision: send it as expectedRevision with the next change.
{
  "status": "applied",
  "operationId": "add-quote-request-1",
  "output": {
    "row": {
      "businessProfileId": "YOUR_BUSINESS_ID",
      "featureId": "juniper-cakes.data",
      "collectionId": "juniper-cakes.quote-requests",
      "id": "0b6f3c2a-5d1e-4f7a-9c8b-2e4d6f8a1c3e"
    },
    "revision": 1
  }
}

Errors

Besides the answers every request can get (Errors), its receipt can say:

Status HTTP What it means
pending 202 Accepted and still running. Look it up with GET /operations/{operationId}.
uncertain 202 GrowLocal can't yet tell whether it took effect. Look it up before trying again.
requirements 409 Something must happen first; the receipt lists what.
conflict 409 The row changed since you read it, or this operationId was used with a different body.
rejected 400, or 403 when it's a matter of access Not done. diagnostics says why: each has a code, a path into what you sent and a message.

The codes in diagnostics you're most likely to see:

Code Status What it means
DATA.REVISION_CONFLICT conflict The row is at another revision than expectedRevision: someone changed it since you read it. Read it again.
DATA.OPERATION_REPLAY_MISMATCH conflict This operationId was already used with a different body. Use a new one.
DATA.FIELD_UNKNOWN rejected The table has no field with that id.
DATA.FIELD_MANAGED rejected That field is written only by GrowLocal's own step for it, such as a status.
DATA.RESOURCE_NOT_FOUND rejected No such table here for this key.