Factory network
Base URL: https://app.trymaglev.com/api/v1. All endpoint families.
GET /factories
Section titled “GET /factories”List the factories Maglev works with. Never carries contact details; at most 50 per page.
Required scope: network:read.
Authentication: bearer key.
| Parameter | Location | Required | Details |
|---|---|---|---|
q |
query | No | Free text over English and Chinese names, specialty, capabilities, city and directory id.. Max length 200 |
process |
query | No | One manufacturing process. A factory matches when this is among the processes it lists.. One of: pcba, injection_molding, cnc, sheet_metal, die_casting, wire_harness, battery, motor_actuator, display, camera, power_adapter, packaging, off_the_shelf, other |
city |
query | No | Matched as a substring, so shen finds Shenzhen.. Max length 80 |
region |
query | No | Matched as a substring, like city.. Max length 80 |
startupFriendly |
query | No | Whether the factory is recorded as willing to take first-batch volumes. unknown is a real value and means nobody has established it.. One of: yes, no, unknown |
answeredUs |
query | No | true, 1 or yes narrows to factories that have answered Maglev. Any other value is ignored rather than refused. |
minQuantityAtMost |
query | No | Keeps factories whose stated minimum is at most this. With process set it reads that process’s minimum, otherwise the lowest the factory states for anything.. Minimum 1. Maximum 10000000 |
confidence |
query | No | How well established the record is. verified means a primary or official source.. One of: verified, reported, unverified |
page |
query | No | 1 when omitted.. Minimum 1. Maximum 100000 |
pageSize |
query | No | 25 when omitted, 50 at most.. Minimum 1. Maximum 50 |
includeQuarantined |
query | No | Maglev keys only, and silently ignored for any other key rather than refused. |
200 response schema
{ "type": "object", "properties": { "factories": { "type": "array", "items": { "$ref": "#/components/schemas/FactoryListItem" } }, "page": { "type": "integer" }, "pageSize": { "type": "integer" }, "total": { "type": "integer" }, "importedThrough": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "requestId": { "type": "string", "description": "Echoed in the X-Request-Id response header. Quote it to Maglev when asking what became of a request." } }, "required": [ "requestId" ]}Errors: 400 Validation error; 401 unauthorized: no bearer key was presented, or the one presented is unknown, expired or revoked. Present a valid key; nothing was done.; 403 Scope or mode does not allow this. On scope_required, details.obtainable says whether a key that carries the scope can be issued at all: true means reissuing this key with the scope would work, false means no key of this kind can ever carry it, because contacts:read and approvals:write are granted on live mode alone and maglev:* belongs to Maglev’s own keys. Stored scopes narrow the grant a mode and organisation already allow, so widening a key never adds one.; 404 Not found; 429 rate_limit: a limit for this key or route is spent. details.retryAfter is how many whole seconds of the refused window remain, at least 1, and the Retry-After header carries the same number. Wait that long rather than assuming a minute; the windows here range from 60 to 86400 seconds. Nothing was done.; 500 internal_error: the request did not complete and the reason was not one this API anticipates. Whether anything was written is unknown. Read error.message, which carries what is safe to do next, and quote the X-Request-Id header to Maglev; the request id is in the body too. Where an operation takes an Idempotency-Key, repeating the request with the same key is the way to learn the earlier outcome without running the work twice, unless the message says to use a new one.. See recovery guidance.
GET /factories/search
Section titled “GET /factories/search”Alias of GET /factories. Same filters, same body; q is the reason to reach for it rather than a requirement of it.
Required scope: network:read.
Authentication: bearer key.
| Parameter | Location | Required | Details |
|---|---|---|---|
q |
query | No | Free text over English and Chinese names, specialty, capabilities, city and directory id.. Max length 200 |
process |
query | No | One manufacturing process. A factory matches when this is among the processes it lists.. One of: pcba, injection_molding, cnc, sheet_metal, die_casting, wire_harness, battery, motor_actuator, display, camera, power_adapter, packaging, off_the_shelf, other |
city |
query | No | Matched as a substring, so shen finds Shenzhen.. Max length 80 |
region |
query | No | Matched as a substring, like city.. Max length 80 |
startupFriendly |
query | No | Whether the factory is recorded as willing to take first-batch volumes. unknown is a real value and means nobody has established it.. One of: yes, no, unknown |
answeredUs |
query | No | true, 1 or yes narrows to factories that have answered Maglev. Any other value is ignored rather than refused. |
minQuantityAtMost |
query | No | Keeps factories whose stated minimum is at most this. With process set it reads that process’s minimum, otherwise the lowest the factory states for anything.. Minimum 1. Maximum 10000000 |
confidence |
query | No | How well established the record is. verified means a primary or official source.. One of: verified, reported, unverified |
page |
query | No | 1 when omitted.. Minimum 1. Maximum 100000 |
pageSize |
query | No | 25 when omitted, 50 at most.. Minimum 1. Maximum 50 |
includeQuarantined |
query | No | Maglev keys only, and silently ignored for any other key rather than refused. |
200 response schema
{ "type": "object", "properties": { "factories": { "type": "array", "items": { "$ref": "#/components/schemas/FactoryListItem" } }, "page": { "type": "integer" }, "pageSize": { "type": "integer" }, "total": { "type": "integer" }, "importedThrough": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "requestId": { "type": "string", "description": "Echoed in the X-Request-Id response header. Quote it to Maglev when asking what became of a request." } }, "required": [ "requestId" ]}Errors: 400 Validation error; 401 unauthorized: no bearer key was presented, or the one presented is unknown, expired or revoked. Present a valid key; nothing was done.; 403 Scope or mode does not allow this. On scope_required, details.obtainable says whether a key that carries the scope can be issued at all: true means reissuing this key with the scope would work, false means no key of this kind can ever carry it, because contacts:read and approvals:write are granted on live mode alone and maglev:* belongs to Maglev’s own keys. Stored scopes narrow the grant a mode and organisation already allow, so widening a key never adds one.; 404 Not found; 429 rate_limit: a limit for this key or route is spent. details.retryAfter is how many whole seconds of the refused window remain, at least 1, and the Retry-After header carries the same number. Wait that long rather than assuming a minute; the windows here range from 60 to 86400 seconds. Nothing was done.; 500 internal_error: the request did not complete and the reason was not one this API anticipates. Whether anything was written is unknown. Read error.message, which carries what is safe to do next, and quote the X-Request-Id header to Maglev; the request id is in the body too. Where an operation takes an Idempotency-Key, repeating the request with the same key is the way to learn the earlier outcome without running the work twice, unless the message says to use a new one.. See recovery guidance.
GET /factories/{id}
Section titled “GET /factories/{id}”One factory by uuid or directory id. Customers receive selected manufacturing fields. Production keys with contacts:read also receive normalized business contacts; each such read is audited and capped at 300 per key per day. Raw directory, source, verification and interaction notes require a live internal maglev:* key.
Required scope: network:read.
Authentication: bearer key.
| Parameter | Location | Required | Details |
|---|---|---|---|
id |
path | Yes | uuid or mfg-, int-, or eng- directory id, such as mfg-sz-robotics-001 |
200 response schema
{ "type": "object", "properties": { "factory": { "type": "object", "properties": { "contacts": { "anyOf": [ { "type": "object", "properties": { "contactName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "contactEmail": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "contactPhone": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "contactWechat": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "directoryFields": { "type": "object", "properties": {} } } }, { "type": "null" } ] }, "contactsNote": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "whatTheyToldUs": { "type": "object", "properties": { "answeredSummary": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "contactedNote": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "communityComments": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "lastAnsweredAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "sources": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } } }, "directoryFields": { "type": "object", "properties": {} }, "certifications": { "type": "array", "items": { "type": "object", "properties": {} } } } }, "requestId": { "type": "string", "description": "Echoed in the X-Request-Id response header. Quote it to Maglev when asking what became of a request." } }, "required": [ "requestId" ]}Errors: 400 Validation error; 401 unauthorized: no bearer key was presented, or the one presented is unknown, expired or revoked. Present a valid key; nothing was done.; 403 Scope or mode does not allow this. On scope_required, details.obtainable says whether a key that carries the scope can be issued at all: true means reissuing this key with the scope would work, false means no key of this kind can ever carry it, because contacts:read and approvals:write are granted on live mode alone and maglev:* belongs to Maglev’s own keys. Stored scopes narrow the grant a mode and organisation already allow, so widening a key never adds one.; 404 Not found; 429 rate_limit: a limit for this key or route is spent. details.retryAfter is how many whole seconds of the refused window remain, at least 1, and the Retry-After header carries the same number. Wait that long rather than assuming a minute; the windows here range from 60 to 86400 seconds. Nothing was done.; 500 internal_error: the request did not complete and the reason was not one this API anticipates. Whether anything was written is unknown. Read error.message, which carries what is safe to do next, and quote the X-Request-Id header to Maglev; the request id is in the body too. Where an operation takes an Idempotency-Key, repeating the request with the same key is the way to learn the earlier outcome without running the work twice, unless the message says to use a new one.. See recovery guidance.
GET /factories/{id}/interactions
Section titled “GET /factories/{id}/interactions”Raw internal mail threads and call notes for a factory. Requires a live internal maglev:* key and is audited. Customer and sandbox keys cannot read this shared correspondence, including snippets and summaries; the legacy interactions:read scope does not grant access.
Required scope: maglev:*.
Authentication: bearer key.
| Parameter | Location | Required | Details |
|---|---|---|---|
id |
path | Yes | |
bodies |
query | No | true includes message bodies and drops the message ceiling from 200 to 20. Any other value, and omitting it, leaves bodies out. |
transcripts |
query | No | true includes call transcripts. Any other value, and omitting it, leaves them out. |
200 response schema
{ "type": "object", "properties": { "factoryId": { "type": "string", "description": "uuid, whichever of the two identifiers the path carried" }, "directoryId": { "anyOf": [ { "type": "string", "description": "The directory id, for example mfg-sz-robotics-001. null for a factory that has no directory record" }, { "type": "null" } ] }, "messageLimit": { "type": "integer", "description": "How many messages this call could return at most: 20 when bodies is true, 200 otherwise" }, "messagesReturned": { "type": "integer", "description": "How many it did return. Equal to messageLimit means the thread history was truncated and this is not the whole correspondence" }, "threads": { "type": "array", "items": { "type": "object", "properties": { "subject": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "firstMessageAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "lastMessageAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "messageCount": { "type": "integer" }, "hasReply": { "type": "boolean" }, "participants": { "type": "array", "items": { "type": "string" } }, "messages": { "type": "array", "items": { "type": "object", "properties": { "senderDomain": { "type": "string" }, "sentAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "body": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } } } } } } }, "callNotes": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "createdAtSource": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "participants": { "type": "array", "items": { "type": "string" } }, "usable": { "type": "string" }, "summaryMarkdown": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "transcriptText": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } } } }, "directoryNotes": { "type": "object", "properties": {} }, "importedThrough": { "anyOf": [ { "type": "string", "description": "Last refresh of the mail mirror" }, { "type": "null" } ] }, "coverageNote": { "type": "string" }, "requestId": { "type": "string", "description": "Echoed in the X-Request-Id response header. Quote it to Maglev when asking what became of a request." } }, "required": [ "requestId" ]}Errors: 400 Validation error; 401 unauthorized: no bearer key was presented, or the one presented is unknown, expired or revoked. Present a valid key; nothing was done.; 403 Scope or mode does not allow this. On scope_required, details.obtainable says whether a key that carries the scope can be issued at all: true means reissuing this key with the scope would work, false means no key of this kind can ever carry it, because contacts:read and approvals:write are granted on live mode alone and maglev:* belongs to Maglev’s own keys. Stored scopes narrow the grant a mode and organisation already allow, so widening a key never adds one.; 404 Not found; 429 rate_limit: a limit for this key or route is spent. details.retryAfter is how many whole seconds of the refused window remain, at least 1, and the Retry-After header carries the same number. Wait that long rather than assuming a minute; the windows here range from 60 to 86400 seconds. Nothing was done.; 500 internal_error: the request did not complete and the reason was not one this API anticipates. Whether anything was written is unknown. Read error.message, which carries what is safe to do next, and quote the X-Request-Id header to Maglev; the request id is in the body too. Where an operation takes an Idempotency-Key, repeating the request with the same key is the way to learn the earlier outcome without running the work twice, unless the message says to use a new one.. See recovery guidance.
GET /network/summary
Section titled “GET /network/summary”Counts of the network visible to this key: total, by process, by region, answered us, with certifications.
Required scope: network:read.
Authentication: bearer key.
200 response schema
{ "type": "object", "properties": { "total": { "type": "integer" }, "byProcess": { "type": "object", "properties": {} }, "byRegion": { "type": "object", "properties": {} }, "answeredUs": { "type": "integer" }, "withCertifications": { "type": "integer" }, "quarantined": { "type": "integer", "description": "How many factories are quarantined, which the other counts exclude. Present only on a maglev key and absent rather than zero on any other, so a customer key reading zero here is reading a field that is not there" }, "importedThrough": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "requestId": { "type": "string", "description": "Echoed in the X-Request-Id response header. Quote it to Maglev when asking what became of a request." } }, "required": [ "requestId" ]}Errors: 400 Validation error; 401 unauthorized: no bearer key was presented, or the one presented is unknown, expired or revoked. Present a valid key; nothing was done.; 403 Scope or mode does not allow this. On scope_required, details.obtainable says whether a key that carries the scope can be issued at all: true means reissuing this key with the scope would work, false means no key of this kind can ever carry it, because contacts:read and approvals:write are granted on live mode alone and maglev:* belongs to Maglev’s own keys. Stored scopes narrow the grant a mode and organisation already allow, so widening a key never adds one.; 404 Not found; 429 rate_limit: a limit for this key or route is spent. details.retryAfter is how many whole seconds of the refused window remain, at least 1, and the Retry-After header carries the same number. Wait that long rather than assuming a minute; the windows here range from 60 to 86400 seconds. Nothing was done.; 500 internal_error: the request did not complete and the reason was not one this API anticipates. Whether anything was written is unknown. Read error.message, which carries what is safe to do next, and quote the X-Request-Id header to Maglev; the request id is in the body too. Where an operation takes an Idempotency-Key, repeating the request with the same key is the way to learn the earlier outcome without running the work twice, unless the message says to use a new one.. See recovery guidance.