Edit Page

Writing Documents

This page explains how to create, update, and delete MongoDB documents through RESTHeart’s REST API.

🔧 Configuration

Sets localhost:8080 with admin:secret
Values are saved in your browser

Create the Inventory Collection

The example requests on this page use the inventory collection. If not already created, run the following:

cURL

curl -i -X PUT [INSTANCE-URL]/inventory -H "Authorization: Basic [BASIC-AUTH]"

curl -i -X POST [INSTANCE-URL]/inventory?wm=upsert -H "Authorization: Basic [BASIC-AUTH]" \
  -d '[
    { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
    { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
    { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
    { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
    { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
  ]'

HTTPie

http PUT [INSTANCE-URL]/inventory Authorization:"Basic [BASIC-AUTH]"

echo '[
   { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
   { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
   { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
   { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
   { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]' | http POST [INSTANCE-URL]/inventory wm==upsert Authorization:"Basic [BASIC-AUTH]"

JavaScript

const data = [
   { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
   { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
   { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
   { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
   { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
];

await fetch('[INSTANCE-URL]/inventory', {
  method: 'PUT',
  headers: { 'Authorization': 'Basic [BASIC-AUTH]' }
});

await fetch('[INSTANCE-URL]/inventory?wm=upsert', {
  method: 'POST',
  body: JSON.stringify(data),
  headers: { 'Authorization': 'Basic [BASIC-AUTH]' }
});

HTTP Methods for Writing Data

RESTHeart uses standard HTTP methods for database operations:

HTTP Method Purpose

POST

Create new documents (generates a new ID if not specified)

PUT

Replace existing documents or create with specified ID

PATCH

Update specific fields in existing documents

DELETE

Remove documents

Content Types

JSON Format (Default)

For write operations, the default content type is application/json:

POST /inventory HTTP/1.1
Content-Type: application/json

{
    "name": "Product XYZ",
    "price": 99.99,
    "available": true,
    "details": {
        "color": "red",
        "size": "medium"
    }
}

Form Data Support

You can also use the following formats (Content-Type):

  • application/x-www-form-urlencoded

  • multipart/form-data

These formats are automatically converted to JSON documents:

POST /collection HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8

name=Product%20XYZ&price=99.99&available=true&details=%7B%22color%22%3A%22red%22%2C%22size%22%3A%22medium%22%7D

Creating Documents

POST - Create with Generated ID

Use POST to create a document and let MongoDB generate an ObjectId:

cURL

curl -i -X POST [INSTANCE-URL]/inventory \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "item": "rubber",
    "qty": 15,
    "size": {
      "h": 2,
      "w": 1,
      "uom": "cm"
    },
    "status": "A"
  }'

HTTPie

http POST [INSTANCE-URL]/inventory \
  Authorization:"Basic [BASIC-AUTH]" \
  item="rubber" \
  qty:=15 \
  size:='{"h": 2, "w": 1, "uom": "cm"}' \
  status="A"

JavaScript

fetch('[INSTANCE-URL]/inventory', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    item: "rubber",
    qty: 15,
    size: {
      h: 2,
      w: 1,
      uom: "cm"
    },
    status: "A"
  })
})
.then(response => {
  if (response.ok) {
    console.log('Resource created successfully');
    console.log('Location:', response.headers.get('Location'));
  } else {
    console.error('Failed to create resource:', response.status);
  }
})
.catch(error => console.error('Error:', error));

The response includes a Location header with the new document’s URI:

HTTP/1.1 201 Created
Location: http://localhost:8080/inventory/61709f718bedc3055e218d7e
Tip
You can specify your own _id in the request body to avoid having MongoDB generate one.

PUT - Create with Specific ID

Use PUT with the ?wm=upsert parameter to create a document with a specific ID:

cURL

curl -i -X PUT "[INSTANCE-URL]/inventory/myCustomId?wm=upsert" \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "item": "pencil",
    "qty": 55,
    "size": {
      "h": 10,
      "w": 0.5,
      "uom": "cm"
    }
  }'

HTTPie

http PUT "[INSTANCE-URL]/inventory/myCustomId?wm=upsert" \
  Authorization:"Basic [BASIC-AUTH]" \
  item="pencil" \
  qty:=55 \
  size:='{"h": 10, "w": 0.5, "uom": "cm"}'

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId?wm=upsert', {
  method: 'PUT',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    item: "pencil",
    qty: 55,
    size: {
      h: 10,
      w: 0.5,
      uom: "cm"
    }
  })
})
.then(response => {
  if (response.ok) {
    console.log('Resource created successfully');
    console.log('Location:', response.headers.get('Location'));
  } else {
    console.error('Failed to create resource:', response.status);
  }
})
.catch(error => console.error('Error:', error));

Updating Documents

PUT - Replace Document

PUT replaces an existing document completely:

PUT /inventory/myCustomId HTTP/1.1

{
  "item": "pencil",
  "qty": 60,
  "size": {
    "h": 15,
    "w": 0.5,
    "uom": "cm"
  }
}
Warning
This replaces the entire document. Any fields not included in the request will be removed.

PATCH - Update Specific Fields

PATCH modifies only the specified fields:

cURL

curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "qty": 75,
    "status": "B"
  }'

HTTPie

http PATCH [INSTANCE-URL]/inventory/myCustomId \
  Authorization:"Basic [BASIC-AUTH]" \
  qty:=75 \
  status="B"

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    qty: 75,
    status: "B"
  })
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This only updates the qty and status fields, leaving all other fields unchanged.

Advanced Update Techniques

Updating Nested Fields with Dot Notation

Access nested document fields and array elements using dot notation:

cURL

curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "size.h": 20
  }'

HTTPie

http PATCH [INSTANCE-URL]/inventory/myCustomId \
  Authorization:"Basic [BASIC-AUTH]" \
  size.h:=20

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "size.h": 20
  })
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This updates only the height property within the size object.

For array elements:

cURL

curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "tags.1": "office"
  }'

HTTPie

http PATCH [INSTANCE-URL]/inventory/myCustomId \
  Authorization:"Basic [BASIC-AUTH]" \
  tags.1="office"

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "tags.1": "office"
  })
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This updates the second element of the tags array.

MongoDB Update Operators

Use MongoDB’s update operators in PATCH requests for more complex updates:

cURL

curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "$inc": { "qty": 1 },
    "$push": { "tags": "school" },
    "$unset": { "discontinued": "" },
    "$currentDate": { "lastModified": true }
  }'

HTTPie

http PATCH [INSTANCE-URL]/inventory/myCustomId \
  Authorization:"Basic [BASIC-AUTH]" \
  Content-Type:application/json \
  '\$inc:={"qty": 1}' \
  '\$push:={"tags": "school"}' \
  '\$unset:={"discontinued": ""}' \
  '\$currentDate:={"lastModified": true}'

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "$inc": { "qty": 1 },
    "$push": { "tags": "school" },
    "$unset": { "discontinued": "" },
    "$currentDate": { "lastModified": true }
  })
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This: - Increments qty by 1 - Adds "school" to the tags array - Removes the discontinued field - Sets lastModified to the current date/time

Tip
See MongoDB Update Operators for all available operators.

Aggregation Pipeline Updates

Since RESTHeart 7.3, you can use MongoDB’s aggregation pipeline for updates:

PATCH /inventory/myCustomId HTTP/1.1

[
  {
    "$set": {
      "tags": {
        "$concatArrays": ["$tags", ["office", "school"]]
      }
    }
  }
]

This adds "office" and "school" to the existing tags array.

Deleting Documents

Use the DELETE method to remove documents:

cURL

curl -i -X DELETE [INSTANCE-URL]/inventory/myCustomId \
  -H "Authorization: Basic [BASIC-AUTH]"

HTTPie

http DELETE [INSTANCE-URL]/inventory/myCustomId \
  Authorization:"Basic [BASIC-AUTH]"

JavaScript

fetch('[INSTANCE-URL]/inventory/myCustomId', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]'
  }
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

Bulk Operations

Perform operations on multiple documents with a single request.

Bulk Inserts

Create multiple documents at once:

cURL

curl -i -X POST [INSTANCE-URL]/inventory \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '[
    { "item": "journal", "qty": 25, "status": "A" },
    { "item": "notebook", "qty": 50, "status": "A" },
    { "item": "paper", "qty": 100, "status": "D" },
    { "item": "planner", "qty": 75, "status": "D" },
    { "item": "postcard", "qty": 45, "status": "A" }
  ]'

HTTPie

echo '[
  { "item": "journal", "qty": 25, "status": "A" },
  { "item": "notebook", "qty": 50, "status": "A" },
  { "item": "paper", "qty": 100, "status": "D" },
  { "item": "planner", "qty": 75, "status": "D" },
  { "item": "postcard", "qty": 45, "status": "A" }
]' | http POST [INSTANCE-URL]/inventory \
  Authorization:"Basic [BASIC-AUTH]" \
  Content-Type:application/json

JavaScript

fetch('[INSTANCE-URL]/inventory', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify([
    { item: "journal", qty: 25, status: "A" },
    { item: "notebook", qty: 50, status: "A" },
    { item: "paper", qty: 100, status: "D" },
    { item: "planner", qty: 75, status: "D" },
    { item: "postcard", qty: 45, status: "A" }
  ])
})
.then(response => {
  if (response.ok) {
    console.log('Resource created successfully');
    console.log('Location:', response.headers.get('Location'));
  } else {
    console.error('Failed to create resource:', response.status);
  }
})
.catch(error => console.error('Error:', error));

Bulk Updates

Update multiple documents using a filter:

cURL

curl -i -X PATCH '[INSTANCE-URL]/inventory/*' \
  --data-urlencode 'filter={"qty":{"$gt":50}}' \
  -H "Authorization: Basic [BASIC-AUTH]" \
  -H "Content-Type: application/json" \
  -d '{
    "highQuantity": true
  }'

HTTPie

http PATCH '[INSTANCE-URL]/inventory/*?filter={"qty":{"$gt":50}}' \
  Authorization:"Basic [BASIC-AUTH]" \
  highQuantity:=true

JavaScript

fetch('[INSTANCE-URL]/inventory/*?filter=' + encodeURIComponent('{"qty":{"$gt":50}}'), {
  method: 'PATCH',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    highQuantity: true
  })
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This adds the highQuantity field to all documents with a quantity greater than 50.

Bulk Deletes

Delete multiple documents matching a filter:

cURL

curl -i -X DELETE '[INSTANCE-URL]/inventory/*' \
  --data-urlencode 'filter={"status":"D"}' \
  -H "Authorization: Basic [BASIC-AUTH]"

HTTPie

http DELETE '[INSTANCE-URL]/inventory/*?filter={"status":"D"}' \
  Authorization:"Basic [BASIC-AUTH]"

JavaScript

fetch('[INSTANCE-URL]/inventory/*?filter=' + encodeURIComponent('{"status":"D"}'), {
  method: 'DELETE',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]'
  }
})
.then(response => {
  if (response.ok) {
    console.log('Write request executed successfully');
  } else {
    console.error('Write request failed:', response.status);
  }
})
.catch(error => console.error('Error:', error));

This deletes all documents with a status of "D".

Important
Bulk operations require special permissions. The default admin user can execute them, but other users need the appropriate permissions.

Write Modes

The ?wm= query parameter can override the default write mode for each HTTP method:

Write Mode Description Example

insert

Create a new document, fail if ID exists

POST /collection?wm=insert

update

Update an existing document, fail if ID doesn’t exist

PUT /collection/docId?wm=update

upsert

Update if exists, create if doesn’t exist

PUT /collection/docId?wm=upsert

Important
The wm parameter requires special permissions. The default admin user can use it, but other users need the allowWriteMode permission.

Reference: Default MongoDB Operations

This table shows which MongoDB operation is executed based on the HTTP method and write mode:

Write Mode Method URI MongoDB Operation Description

insert

POST

/coll

insertOne

Create document with generated ID

insert

PUT

/coll/docid

insertOne

Create document with specified ID

insert

PATCH

/coll/docid

findOneAndUpdate(upsert:true)

Insert with update operators

update

POST

/coll

findOneAndReplace(upsert:false)

Replace existing document

update

PUT

/coll/docid

findOneAndReplace(upsert:false)

Replace existing document

update

PATCH

/coll/docid

findOneAndUpdate(upsert:false)

Update specific fields

upsert

POST

/coll

findOneAndReplace(upsert:true)

Replace or create with body ID

upsert

PUT

/coll/docid

findOneAndReplace(upsert:true)

Replace or create with URI ID

upsert

PATCH

/coll/docid

findOneAndUpdate(upsert:true)

Update fields or create

Bold entries indicate default behavior when no wm parameter is specified.