{"info":{"name":"Morph Embedded","description":"Morph Embedded's vendor API. Set the server_key variable to a key from Settings → Morph Embedded.","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json"},"auth":{"type":"bearer","bearer":[{"key":"token","value":"{{server_key}}","type":"string"}]},"variable":[{"key":"base_url","value":"https://morph-vereon.com/embedded/v1"},{"key":"server_key","value":""},{"key":"job_id","value":""},{"key":"batch_id","value":""},{"key":"mapping_id","value":""},{"key":"key","value":"Invoice"},{"key":"external_id","value":"cust_123"}],"item":[{"name":"Importer sessions","item":[{"name":"Start an importer session for one customer","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/sessions","host":["{{base_url}}"],"path":["sessions"]},"description":"Call from your server each time a customer opens the importer, and hand the token to your page (MorphImporter.open's getSessionToken). The customer is added the first time Morph sees their id. A session lasts 15 minutes. language (en, fr, de, es or nl) sets the importer's and Connect's language for this session, over your setting in Settings; a language given on the page itself wins over both.","body":{"mode":"raw","raw":"{\n  \"tenant\": \"cust_123\",\n  \"tenant_name\": \"Brook Supplies\",\n  \"user\": {\n    \"id\": \"user_42\"\n  },\n  \"language\": \"fr\"\n}","options":{"raw":{"language":"json"}}}}}]},{"name":"Engine","item":[{"name":"Send one file through the engine","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/jobs","host":["{{base_url}}"],"path":["jobs"]},"description":"Morph maps the file itself (the customer's saved mapping for this layout, then your standard, then its own matching), checks and converts every row, and delivers the records like an import. When a required field can't be matched with confidence the job stops as needs_mapping with questions; confirm once with POST /mappings and that layout maps itself from then on. Inline files up to 4 MB. By file.url, a CSV up to 2 GB, read as it arrives (never held whole), and a workbook up to 50 MB. A workbook is read from its first sheet with data, or from the sheet named in sheet: send a workbook with a sheet per data type once per sheet. A PDF or a scan (.pdf, .png, .jpg, .tif) is read with OCR into one record of your fields when you've switched on documents in Settings, or into a record per line of the invoice when the schema's documentLines is on (the document's own fields on every line).","body":{"mode":"raw","raw":"{\n  \"tenant\": \"cust_123\",\n  \"tenant_name\": \"Brook Supplies\",\n  \"target_schema\": \"Invoice\",\n  \"file\": {\n    \"url\": \"https://files.example.com/invoices.csv\"\n  }\n}","options":{"raw":{"language":"json"}}}}},{"name":"A job's status, counts and questions","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/jobs/{{job_id}}","host":["{{base_url}}"],"path":["jobs","{{job_id}}"]},"description":"status: queued, running, completed, failed or needs_mapping (then with columns, suggested_mapping and questions)."}},{"name":"A customer's latest jobs","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/jobs","host":["{{base_url}}"],"path":["tenants","{{external_id}}","jobs"]},"description":"Newest first, for about a week: the files you sent, and the files the customer sent to their email address or SFTP folder (via email or sftp). A job that stopped as needs_mapping has the file's columns and questions: confirm once with POST /mappings and that layout maps itself from then on. Morph doesn't keep the file, so the customer sends that one again."}}]},{"name":"Email and SFTP","item":[{"name":"A customer's email addresses","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/inboxes","host":["{{base_url}}"],"path":["tenants","{{external_id}}","inboxes"]}}},{"name":"Give a customer an email address for one schema","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/inboxes","host":["{{base_url}}"],"path":["tenants","{{external_id}}","inboxes"]},"description":"Each file attached to an email sent to the address (CSV, TSV or Excel; a PDF or scan when documents are on), up to 20 an email, goes through the customer's saved mapping for its layout, then your standard and Morph's matching, and is delivered like an import, as a job (GET /tenants/{external_id}/jobs). A file Morph can't map with confidence stops as needs_mapping. Anyone holding the address can send files for the customer: switch it off with DELETE /inboxes/{inbox_id}. Neither the email nor its files are kept.","body":{"mode":"raw","raw":"{\n  \"schema\": \"Invoice\"\n}","options":{"raw":{"language":"json"}}}}},{"name":"Switch an email address off","request":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/inboxes/{{inbox_id}}","host":["{{base_url}}"],"path":["inboxes","{{inbox_id}}"]},"description":"Mail sent to it from now on is dropped."}},{"name":"A customer's SFTP folder","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/sftp","host":["{{base_url}}"],"path":["tenants","{{external_id}}","sftp"]}}},{"name":"Give a customer an SFTP folder, or replace its key","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/sftp","host":["{{base_url}}"],"path":["tenants","{{external_id}}","sftp"]},"description":"The customer signs in with their SSH key (keys only, never a password) and finds a folder for each of your schemas: a file put in /Invoice is imported as Invoice, through their saved mapping like a file sent by email, as a job. Each file leaves the folder once read. A new key replaces the old one. Answers 201 when the folder is new.","body":{"mode":"raw","raw":"{\n  \"public_key\": \"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGqK0b5Yx3bXcW3yH8sQ1lqfLr6ZfNnS6rC2u0Q9d1hX brook@laptop\"\n}","options":{"raw":{"language":"json"}}}}},{"name":"Remove a customer's SFTP folder","request":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/sftp","host":["{{base_url}}"],"path":["tenants","{{external_id}}","sftp"]},"description":"Nobody can sign in as the customer again, and anything still in the folder is deleted."}}]},{"name":"Records","item":[{"name":"Collect an import's records (once)","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/batches/{{batch_id}}","host":["{{base_url}}"],"path":["batches","{{batch_id}}"]},"description":"For imports not sent to a webhook. Each record is returned once and then deleted; a large import comes in pages, so call again while remaining_parts is above zero. Undelivered imports are deleted after 24 hours."}}]},{"name":"Import logs","item":[{"name":"A customer's import logs","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/logs","host":["{{base_url}}"],"path":["tenants","{{external_id}}","logs"]},"description":"Each import and each Connect sync run of the last 30 days: what came in, the rows with problems (row, field, why), what your app refused and where the records went. Never a value. Show them in your product so customers can see what happened."}},{"name":"One import log","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/logs/{{id}}","host":["{{base_url}}"],"path":["logs","{{id}}"]}}}]},{"name":"Connect","item":[{"name":"A customer's connected systems and their syncs","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/connections","host":["{{base_url}}"],"path":["tenants","{{external_id}}","connections"]},"description":"The systems a customer connected in the Connect window, each with the syncs that bring its records into your schemas. A system built with your own connector has provider \"custom\" and its connectorId. Never a credential."}},{"name":"Write a customer's records into their connected systems","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/writes","host":["{{base_url}}"],"path":["tenants","{{external_id}}","writes"]},"description":"Your records, in one of your schemas, written into each of the customer's connected systems you write that schema into (Settings → Morph Embedded → Connect), or only into connection_id. Each system gets its own write, checked like an import and written in the background, once: the write's import log and the records.written event say what was written and what the system refused. Up to 500 records per call.","body":{"mode":"raw","raw":"{\n  \"schema\": \"Customer\",\n  \"records\": [\n    {\n      \"name\": \"Brook Supplies Ltd\",\n      \"email\": \"accounts@brook.example\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}}},{"name":"Remove a customer's connection","request":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}/connections/{{id}}","host":["{{base_url}}"],"path":["tenants","{{external_id}}","connections","{{id}}"]},"description":"Morph forgets the sign-in and stops its syncs. connection.disconnected is sent."}},{"name":"Run a sync now","request":{"method":"POST","header":[],"url":{"raw":"{{base_url}}/syncs/{{id}}/run","host":["{{base_url}}"],"path":["syncs","{{id}}","run"]},"description":"Brings what changed since the last run straight away, delivered like an import."}}]},{"name":"Audit log","item":[{"name":"Who did what, and when","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/audit","host":["{{base_url}}"],"path":["audit"]},"description":"Newest first: what your team changed in Settings, what your server did (by key), what your customers did in the importer and the Connect window, and what Morph did on its own. Ids, the names of settings that changed, and counts: never a value, a secret or a row. Kept 400 days; a customer's entries go when the customer is deleted. For the next page, send next_before as before."}}]},{"name":"Schemas","item":[{"name":"Create or change a target schema","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/schemas/{{key}}","host":["{{base_url}}"],"path":["schemas","{{key}}"]},"description":"Saving a changed schema moves its version on by one; saving it unchanged does nothing.","body":{"mode":"raw","raw":"{\n  \"label\": \"Invoice\",\n  \"keyField\": \"invoice_number\",\n  \"fields\": [\n    {\n      \"name\": \"invoice_number\",\n      \"label\": \"Invoice number\",\n      \"type\": \"string\",\n      \"required\": true,\n      \"unique\": true,\n      \"aliases\": [\n        \"Inv No\",\n        \"Invoice #\"\n      ]\n    },\n    {\n      \"name\": \"amount\",\n      \"label\": \"Amount\",\n      \"type\": \"number\",\n      \"required\": true\n    },\n    {\n      \"name\": \"due_date\",\n      \"label\": \"Due date\",\n      \"type\": \"date\",\n      \"transforms\": [\n        {\n          \"kind\": \"parse_date\",\n          \"format\": \"DD/MM/YYYY\"\n        }\n      ]\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}}},{"name":"List target schemas","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/schemas","host":["{{base_url}}"],"path":["schemas"]}}},{"name":"One target schema","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/schemas/{{key}}","host":["{{base_url}}"],"path":["schemas","{{key}}"]}}},{"name":"Delete a target schema","request":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/schemas/{{key}}","host":["{{base_url}}"],"path":["schemas","{{key}}"]}}}]},{"name":"Customers","item":[{"name":"Add a customer (safe to repeat)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/tenants","host":["{{base_url}}"],"path":["tenants"]},"description":"Optional: POST /sessions and POST /jobs add the customer themselves.","body":{"mode":"raw","raw":"{\n  \"external_id\": \"cust_123\",\n  \"name\": \"Brook Supplies\"\n}","options":{"raw":{"language":"json"}}}}},{"name":"List customers","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/tenants","host":["{{base_url}}"],"path":["tenants"]}}},{"name":"Delete a customer and everything Morph holds for them","request":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/tenants/{{external_id}}","host":["{{base_url}}"],"path":["tenants","{{external_id}}"]}}}]},{"name":"Headless mapping","item":[{"name":"Describe columns without keeping values","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/profile","host":["{{base_url}}"],"path":["profile"]},"description":"Types, empty share, date formats and value shapes per column. No cell is returned or kept.","body":{"mode":"raw","raw":"{\n  \"columns\": [\n    \"Inv No\",\n    \"Total\",\n    \"Due\"\n  ],\n  \"rows\": [\n    [\n      \"INV-1\",\n      \"1,200.50\",\n      \"31/03/2026\"\n    ],\n    [\n      \"INV-2\",\n      \"88\",\n      \"01/04/2026\"\n    ]\n  ]\n}","options":{"raw":{"language":"json"}}}}},{"name":"Suggest a mapping for a file's columns","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/mappings/suggest","host":["{{base_url}}"],"path":["mappings","suggest"]},"body":{"mode":"raw","raw":"{\n  \"tenant\": \"cust_123\",\n  \"target_schema\": \"Invoice\",\n  \"columns\": [\n    \"Inv No\",\n    \"Total\",\n    \"Due\"\n  ],\n  \"sample\": [\n    [\n      \"INV-1\",\n      \"1,200.50\",\n      \"31/03/2026\"\n    ]\n  ]\n}","options":{"raw":{"language":"json"}}}}},{"name":"Save a customer's confirmed mapping","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/mappings","host":["{{base_url}}"],"path":["mappings"]},"description":"Files with the same columns from this customer then map themselves (POST /jobs without a mapping).","body":{"mode":"raw","raw":"{\n  \"tenant\": \"cust_123\",\n  \"target_schema\": \"Invoice\",\n  \"columns\": [\n    \"Inv No\",\n    \"Total\",\n    \"Due\"\n  ],\n  \"mapping\": {\n    \"invoice_number\": {\n      \"column\": \"Inv No\"\n    },\n    \"amount\": {\n      \"column\": \"Total\"\n    },\n    \"due_date\": {\n      \"column\": \"Due\"\n    }\n  }\n}","options":{"raw":{"language":"json"}}}}},{"name":"One saved mapping","request":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/mappings/{{mapping_id}}","host":["{{base_url}}"],"path":["mappings","{{mapping_id}}"]}}},{"name":"Check records against a schema","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/validate","host":["{{base_url}}"],"path":["validate"]},"body":{"mode":"raw","raw":"{\n  \"target_schema\": \"Invoice\",\n  \"records\": [\n    {\n      \"invoice_number\": \"INV-1\",\n      \"amount\": 1200.5\n    }\n  ]\n}","options":{"raw":{"language":"json"}}}}},{"name":"Map, convert and check rows in one call","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{base_url}}/transform","host":["{{base_url}}"],"path":["transform"]},"body":{"mode":"raw","raw":"{\n  \"target_schema\": \"Invoice\",\n  \"columns\": [\n    \"Inv No\",\n    \"Total\",\n    \"Due\"\n  ],\n  \"mapping\": {\n    \"invoice_number\": {\n      \"column\": \"Inv No\"\n    },\n    \"amount\": {\n      \"column\": \"Total\"\n    },\n    \"due_date\": {\n      \"column\": \"Due\"\n    }\n  },\n  \"rows\": [\n    [\n      \"INV-1\",\n      \"1,200.50\",\n      \"31/03/2026\"\n    ]\n  ]\n}","options":{"raw":{"language":"json"}}}}}]}]}