Data connector#
The data connector fills a NAMES LEGAL site from data that already exists elsewhere, without code on the site owner's side. The owner connects a source in their console (Integrations → Import my data), links columns to fields with drag and drop, runs a trial, and launches. Sources can be files or an API — yours.
This page is for developers of applications that want to be a source: what NAMES LEGAL expects from your API, and how to make the connection automatic.
How the connector reads your API#
The site owner enters:
- the address of your API,
- an authentication mode and its secret,
- optionally, where the list is in your answer (
data.items).
NAMES LEGAL then calls your API over HTTPS with GET, follows pagination, and turns every object into a line. Nested objects are flattened (author.name), lists of plain values are joined with commas.
Authentication#
| Mode | What is sent |
|---|---|
| None | nothing |
| Key in a header | <Header-Name>: <key> (default X-API-Key) |
| Key in the address | ?<param>=<key> (default api_key) |
| Bearer token | Authorization: Bearer <token> |
| Username and password | Authorization: Basic … |
Secrets are stored encrypted and are never shown again in the console. Give site owners a read-only key limited to published content: the connector only reads.
Finding the list#
If no path is given, the connector takes, in order: the items array, then the first array of objects found in the answer. A bare JSON array works too.
Pagination#
Any of these is followed automatically, up to 200 pages:
- an HTTP
Link: <…>; rel="next"header; - a next-page URL in the body:
next,next_url,next_page_url,links.next,meta.next,pagination.next; - a cursor in the body:
next_cursor,meta.next_cursor,pagination.next_cursor— sent back as?cursor=.
Stop by returning an empty list or no next link.
Limits#
- 5,000 lines per data set and synchronisation.
- 10 MB per answer, 15 seconds per request.
- Addresses must be public: private and local network addresses are refused, redirections included. On a redirection to another host, your key is not forwarded.
The NAMES LEGAL feed format#
Expose your data in this format and the site owner has nothing to link: each collection becomes a data set already connected to the matching section of the site.
1. An index#
GET https://app.example.com/api/names-legal/
{
"names_legal_feed": 1,
"collections": {
"team": "https://app.example.com/api/names-legal/team/",
"services": "https://app.example.com/api/names-legal/programmes/",
"blog": "https://app.example.com/api/names-legal/news/"
}
}
Collection names are the section keys listed in the field reference below (team, services, blog, events, faq, jobs…). URLs may be relative to the index.
2. One list per collection#
{
"items": [
{
"id": "T-104",
"first_name": "Awa",
"last_name": "Diop",
"position": "Mathematics teacher",
"short_bio": "Twelve years of teaching.",
"profile_image": "https://app.example.com/media/staff/104.jpg",
"email": "a.diop@example.com"
}
],
"next": null
}
Rules:
id— a stable identifier, different on every line. It is how an edited line updates the same entry instead of creating a new one.- Field names are those of the field reference.
- Translated fields take one key per language:
title_fr,title_en,description_de… A key without suffix goes to the site's default language. - Images and files are public URLs. They are downloaded once and downloaded again only when the URL changes. Google Drive and Dropbox share links are accepted.
- Categories are given by name (
"category": "Bachelor"); missing categories are created. - Dates are ISO 8601. Booleans are
true/false. - Rich text fields accept HTML; it is cleaned (no scripts, no event handlers). Plain text becomes paragraphs.
- Only return what may be published: drafts and private data should not appear in the feed.
Keeping the site up to date#
The site owner chooses, per section:
| Option | Effect |
|---|---|
| Every hour / every day | NAMES LEGAL reads your API on schedule. |
| Only when I ask | A button in the console. |
| Webhook | You call the site's webhook address after each change: synchronisation within a minute. See Webhooks. |
They also choose what happens when an entry changed on both sides (your data wins, the site wins, or ask), and when a line disappears from your feed (delete on the site, hide, or keep). A synchronisation that would remove a large share of a section stops and asks for confirmation first.
Writing back to your application ("my site → my source") is not available yet: the connector only reads.
Field reference#
Generated from the platform itself; it is always up to date. Required fields must be present on every line (for a translated field, in at least one language).
Team team
| Field | Field type | Required | One per language |
|---|---|---|---|
first_nameFirst name |
text ≤ 100 | ✓ | |
last_nameLast name |
text ≤ 100 | ✓ | |
positionPosition |
text ≤ 150 | ✓ | |
short_bioShort bio |
longtext ≤ 300 | ||
bioBio |
html | ||
profile_imageProfile image |
image ≤ 100 | ||
email |
email ≤ 254 | ||
phonePhone |
text ≤ 20 | ||
linkedin |
url ≤ 200 | ||
websitePersonal website |
url ≤ 200 | ||
specialtiesSpecialties |
text ≤ 200 | ||
educationEducation |
text ≤ 200 | ||
locationLocation |
text ≤ 100 | ||
years_experienceYears of experience |
int | ||
orderOrder |
int |
Services services
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 100 | ✓ | title_fr, title_en… |
descriptionDescription |
longtext | ✓ | description_fr, description_en… |
iconIcon |
text ≤ 50 | ||
categoryCategory |
category | ||
is_featuredFeatured service |
bool | ||
orderOrder |
int |
Projects projects
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 150 | ✓ | title_fr, title_en… |
descriptionShort description |
longtext | ✓ | description_fr, description_en… |
detailed_descriptionDetailed description |
html | detailed_description_fr, detailed_description_en… |
|
categoryCategory |
category | ✓ | |
imageFeatured image |
image ≤ 100 | ||
clientClient |
text ≤ 100 | client_fr, client_en… |
|
project_dateProject date |
text ≤ 20 | ||
durationDuration |
text ≤ 50 | duration_fr, duration_en… |
|
project_urlLive project url |
url ≤ 200 | ||
technologiesTechnologies |
text ≤ 200 | technologies_fr, technologies_en… |
|
tagsTags |
text ≤ 200 | tags_fr, tags_en… |
|
statusStatus |
choice ≤ 20completed, in_progress, on_hold, planning |
||
is_featuredFeatured project |
bool | ||
orderOrder |
int |
Blog / news blog
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 200 | ✓ | title_fr, title_en… |
excerptExcerpt |
longtext ≤ 500 | ✓ | excerpt_fr, excerpt_en… |
contentContent |
html | ✓ | content_fr, content_en… |
categoryCategory |
category | ✓ | |
featured_imageFeatured image |
image ≤ 100 | ||
published_datePublished date |
datetime | ||
statusStatus |
choice ≤ 20draft, published, featured |
||
orderOrder |
int |
Events events
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 200 | ✓ | title_fr, title_en… |
descriptionDescription |
html | ✓ | description_fr, description_en… |
start_dateStart date |
datetime | ✓ | |
end_dateEnd date |
datetime | ✓ | |
locationLocation |
text ≤ 200 | ✓ | location_fr, location_en… |
is_onlineIs online |
bool | ||
event_typeEvent type |
choice ≤ 20conference, workshop, webinar, seminar, training, meeting |
||
registration_urlRegistration url |
url ≤ 200 | ||
meeting_urlMeeting url |
url ≤ 200 | ||
featured_imageFeatured image |
image ≤ 100 | ||
is_featuredIs featured |
bool | ||
orderOrder |
int |
FAQ faq
| Field | Field type | Required | One per language |
|---|---|---|---|
questionQuestion |
text ≤ 300 | ✓ | question_fr, question_en… |
answerAnswer |
html | ✓ | answer_fr, answer_en… |
categoryCategory |
category | ||
is_featuredIs featured |
bool | ||
orderOrder |
int |
Job openings jobs
| Field | Field type | Required | One per language |
|---|---|---|---|
titleJob title |
text ≤ 200 | ✓ | |
categoryCategory |
category | ✓ | |
descriptionJob description |
html | ✓ | |
requirementsRequirements |
html | ✓ | |
responsibilitiesResponsibilities |
html | ||
benefitsBenefits |
html | ||
locationLocation |
text ≤ 200 | ✓ | |
contract_typeContract type |
choice ≤ 20full_time, part_time, contract, freelance, internship, temporary |
||
experience_levelExperience level |
choice ≤ 20entry, junior, mid, senior, lead, executive |
||
remote_optionRemote option |
choice ≤ 20onsite, remote, hybrid |
||
application_deadlineApplication deadline |
date | ||
is_activeActive |
bool |
Resources resources
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 200 | ✓ | title_fr, title_en… |
descriptionDescription |
html | ✓ | description_fr, description_en… |
fileFile |
file ≤ 100 | ✓ | |
resource_typeResource type |
choice ≤ 20guide, ebook, whitepaper, template, checklist, case_study |
||
thumbnailThumbnail |
image ≤ 100 | ||
orderOrder |
int |
Publications publications
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 255 | ✓ | title_fr, title_en… |
authorsAuthors |
text ≤ 255 | ✓ | authors_fr, authors_en… |
yearYear |
text ≤ 10 | ✓ | |
journalJournal |
text ≤ 255 | journal_fr, journal_en… |
|
abstractAbstract |
html | abstract_fr, abstract_en… |
|
linkLink |
url ≤ 200 | ||
categoryCategory |
category | ||
is_featuredFeatured publication |
bool | ||
orderOrder |
int |
Testimonials testimonials
| Field | Field type | Required | One per language |
|---|---|---|---|
nameName |
text ≤ 100 | ✓ | name_fr, name_en… |
positionPosition |
text ≤ 100 | ✓ | position_fr, position_en… |
testimonialTestimonial |
longtext | ✓ | testimonial_fr, testimonial_en… |
ratingRating |
int | ||
imageImage |
image ≤ 100 | ||
orderOrder |
int |
Skills skills
| Field | Field type | Required | One per language |
|---|---|---|---|
nameName |
text ≤ 100 | ✓ | name_fr, name_en… |
levelLevel |
int | ||
orderOrder |
int |
Key figures stats
| Field | Field type | Required | One per language |
|---|---|---|---|
titleTitle |
text ≤ 100 | ✓ | title_fr, title_en… |
valueValue |
text ≤ 20 | ✓ | |
iconIcon |
text ≤ 50 | ||
orderOrder |
int |