Getting started
Introduction
The Business API does from your own software what you do in the Gogenx dashboard: add businesses and send them for review, keep their details, blog posts, logo and photos up to date, and take them out of view. Every request and response is application/json.
https://gogenx.ai/api/public/v1A few things hold everywhere:
- It follows the same rules as the dashboard. A new business is reviewed by our team before it goes live, starts on the Free plan, and keeps its plan’s limits. Plans are chosen and paid for in the dashboard.
- What you read, you can send back. Field names are the same going in and coming out, so a business read with Get Business can be changed and sent to Update Business as it is.
- Only your own account. A key reaches the businesses of the account that made it, and nothing else. Anything else answers “not found”.
- Unknown fields are refused, not ignored, so a misspelt field name is an error you see rather than a change that silently did not happen.
Getting started
Authentication
Send your API key as a bearer token in the Authorization header of every request.
curl "https://gogenx.ai/api/public/v1/businesses" \
-H "Authorization: Bearer gxk_your_api_key"- Getting a key. Sign in to Gogenx, open API & Keys and press Generate API key. It is shown once — copy it then.
- One key per account. Rotate API key gives you a new one and stops the old one at once, so update your software straight after.
- Keep it on your server. Anyone holding the key can change your businesses. Never put it in a web page, an app people download, or a URL.
A missing, wrong or rotated key answers 401 UNAUTHENTICATED.
Getting started
Limits
Every account has the same allowance: 10,000 requests a month, and 120 requests a minute per key.
- The month is the calendar month in UTC; the count starts again on the 1st. Every call counts, including one refused for a mistake. Categories does not count.
- Every response says where you are, in
X-Api-Quota-Limit,X-Api-Quota-RemainingandX-Api-Quota-Reset(when the count starts again). - Past the allowance calls answer
429 API_QUOTA_EXCEEDEDuntil the reset. Over the per-minute limit they answer429 RATE_LIMITED— wait a moment and retry. - Businesses keep the dashboard’s limits: one logo (up to 2 MB) and 10 photos (up to 8 MB each) per business, post covers up to 5 MB, and 5 FAQs on a Free business or 25 on Pro and Scale.
Over the monthly allowance · 429 Too Many Requests
{
"error": {
"code": "API_QUOTA_EXCEEDED",
"message": "This account has used all 10,000 API requests for this month. The allowance resets on 2026-10-01.",
"requestId": "req_8f14e45f-ceea-467a-9575-5a3c1c2f3a1b",
"details": []
}
}/businessesCreate Business
Adds a business and sends it for review in one call. It starts on the Free plan with the status submitted, and goes live (active) when our team approves it.
Send the fields in Business fields. These are required: businessName, primaryCategoryCode, streetAddress, city, stateRegion, postalCode (except in countries without postal codes), countryCode, publicPhone, contactFirstName, contactLastName, businessContactEmail, and a description or shortDescription.
If anything required is missing, nothing is created and the error names every missing field at once. Send an Idempotency-Key header so that retrying after a timeout cannot create the business twice — see Safe retries.
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: blue-sky-bakery-austin" \
-d '{
"businessName": "Blue Sky Bakery",
"primaryCategoryCode": "bakeries",
"additionalCategoryCodes": ["coffee-houses-and-tea-rooms"],
"shortDescription": "Sourdough, pastries and coffee, baked fresh every morning.",
"description": "A neighbourhood bakery in downtown Austin. Everything is baked on site from 5am, with a slow-rise sourdough, seasonal pastries and locally roasted coffee.",
"streetAddress": "123 Main St",
"city": "Austin",
"stateRegion": "TX",
"postalCode": "78701",
"countryCode": "US",
"latitude": 30.2672,
"longitude": -97.7431,
"timezone": "America/Chicago",
"publicPhone": "+1 512 555 0142",
"publicEmail": "hello@blueskybakery.com",
"website": "https://blueskybakery.com",
"contactFirstName": "Casey",
"contactLastName": "Rivera",
"businessContactEmail": "casey@blueskybakery.com",
"hours": {
"days": {
"mon": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"tue": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"wed": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"thu": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"fri": { "closed": false, "intervals": [{ "open": "07:00", "close": "18:00" }] },
"sat": { "closed": false, "intervals": [{ "open": "08:00", "close": "14:00" }] },
"sun": { "closed": true, "intervals": [] }
}
},
"services": [
{
"name": "Celebration cakes",
"description": "Made to order, 48 hours notice.",
"priceMinor": 4500,
"currency": "USD"
}
],
"faqs": [
{
"question": "Do you bake gluten-free bread?",
"answer": "Yes, every Friday, in a separate oven."
}
],
"languages": ["English", "Spanish"],
"paymentMethodLabels": ["Cash", "Visa", "Apple Pay"],
"attributes": ["Wheelchair accessible", "Outdoor seating"],
"socialProfiles": {
"profiles": [{ "provider": "instagram", "url": "https://instagram.com/blueskybakery" }]
}
}'Response · 201 Created
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "submitted",
"plan": "free",
"businessName": "Blue Sky Bakery",
"submittedAt": "2026-09-17T09:30:00.000Z",
"createdAt": "2026-09-17T09:30:41.000Z",
"…": "every other field, as in Get Business"
}
}When required details are missing
Response · 400 Bad Request
{
"error": {
"code": "LISTING_INCOMPLETE",
"message": "Some required details are missing, so nothing was created.",
"requestId": "req_8f14e45f-ceea-467a-9575-5a3c1c2f3a1b",
"details": [
{ "field": "primaryCategoryCode", "message": "Category is required." },
{ "field": "streetAddress", "message": "Street address is required." },
{ "field": "stateRegion", "message": "State or region is required." },
{ "field": "postalCode", "message": "Postal code is required." },
{ "field": "countryCode", "message": "Country is required." },
{ "field": "publicPhone", "message": "Phone number is required." },
{ "field": "contactFirstName", "message": "Contact first name is required." },
{ "field": "contactLastName", "message": "Contact last name is required." },
{ "field": "businessContactEmail", "message": "Business contact email is required." },
{ "field": "description", "message": "A description of the business is required." }
]
}
}/businessesList Businesses
The businesses on your account, newest first, a page at a time. Deleted businesses are not included.
| Query | Type | Description |
|---|---|---|
| page | integer | Which page. Starts at 1, which is the default. |
| limit | integer | Businesses per page, 1 to 100. Defaults to 20. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses?page=1&limit=20" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"businesses": [
{
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"businessName": "Blue Sky Bakery",
"status": "submitted",
"plan": "free",
"city": "Austin",
"stateRegion": "TX",
"countryCode": "US",
"createdAt": "2026-09-17T09:30:41.000Z",
"updatedAt": "2026-09-17T09:30:00.000Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 1, "totalPages": 1 }
}/businesses/:idGet Business
One business, with every field.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "submitted",
"plan": "free",
"businessName": "Blue Sky Bakery",
"legalEntityName": null,
"shortDescription": "Sourdough, pastries and coffee, baked fresh every morning.",
"description": "A neighbourhood bakery in downtown Austin. Everything is baked on site from 5am, with a slow-rise sourdough, seasonal pastries and locally roasted coffee.",
"primaryCategoryCode": "bakeries",
"additionalCategoryCodes": ["coffee-houses-and-tea-rooms"],
"industryVertical": null,
"yearEstablished": null,
"teamSize": null,
"numberOfEmployees": null,
"priceRange": null,
"mission": null,
"uniqueValueClaims": null,
"publicPhone": "+1 512 555 0142",
"mobilePhone": null,
"publicEmail": "hello@blueskybakery.com",
"website": "https://blueskybakery.com",
"bookingUrl": null,
"menuUrl": null,
"googleMapsUrl": null,
"contactFirstName": "Casey",
"contactLastName": "Rivera",
"businessContactEmail": "casey@blueskybakery.com",
"streetAddress": "123 Main St",
"city": "Austin",
"stateRegion": "TX",
"postalCode": "78701",
"countryCode": "US",
"latitude": 30.2672,
"longitude": -97.7431,
"timezone": "America/Chicago",
"serviceArea": null,
"hours": {
"schemaVersion": 1,
"days": {
"mon": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"tue": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"wed": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"thu": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"fri": { "closed": false, "intervals": [{ "open": "07:00", "close": "18:00" }] },
"sat": { "closed": false, "intervals": [{ "open": "08:00", "close": "14:00" }] },
"sun": { "closed": true, "intervals": [] }
}
},
"attributes": ["Wheelchair accessible", "Outdoor seating"],
"languages": ["English", "Spanish"],
"paymentMethodLabels": ["Cash", "Visa", "Apple Pay"],
"socialProfiles": {
"profiles": [{ "url": "https://instagram.com/blueskybakery", "provider": "instagram" }],
"schemaVersion": 1
},
"brandColors": [],
"brandColorUsageNote": null,
"businessSizeTarget": null,
"targetAudienceDescription": null,
"keywords": [],
"services": [
{
"name": "Celebration cakes",
"description": "Made to order, 48 hours notice.",
"priceMinor": 4500,
"currency": "USD",
"priceNote": null
}
],
"faqs": [
{
"question": "Do you bake gluten-free bread?",
"answer": "Yes, every Friday, in a separate oven."
}
],
"submittedAt": "2026-09-17T09:30:00.000Z",
"activatedAt": null,
"createdAt": "2026-09-17T09:30:41.000Z",
"updatedAt": "2026-09-17T09:30:00.000Z"
}
}A field with nothing in it is null or an empty list, never a placeholder.
/businesses/:idUpdate Business
Changes the fields you send; everything you leave out stays as it is. PUT works the same way.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
- Sending
nullclears a field that can be empty. Required fields cannot be cleared. - Lists are replaced whole. Sending
faqs,servicesorkeywordsreplaces the list with the one you send. - A business read with Get Business can be sent back as it is. Its
id,statusandplanare accepted unchanged but cannot be changed here, and its timestamps are ignored. - A live business stays live while it is edited. Its new details are read by our automatic content check.
Example request
curl -X PATCH "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "publicPhone": "+1 512 555 0199", "website": "https://www.blueskybakery.com" }'Response · 200 OK
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "submitted",
"businessName": "Blue Sky Bakery",
"publicPhone": "+1 512 555 0199",
"website": "https://www.blueskybakery.com",
"updatedAt": "2026-09-17T09:32:44.000Z",
"…": "every other field, as in Get Business"
}
}/businesses/:id/submitSubmit for Review
Sends a business for review: a draft started in the dashboard, or one our team sent back (rejected) once you have fixed it. Businesses made with Create Business are sent automatically.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/submit" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "submitted",
"businessName": "Blue Sky Bakery East",
"submittedAt": "2026-09-17T09:33:25.000Z",
"…": "every other field, as in Get Business"
}
}/businesses/:idDeactivate Business
Takes a live business out of public view. Its data is kept, its status becomes paused, and you can switch it back on with Reactivate Business or in the dashboard.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
Deactivating does not cancel a paid plan. When the business is on Pro or Scale, the response includes a notice saying so; cancel the plan in the dashboard if you no longer need it.
Example request
curl -X DELETE "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "paused",
"plan": "free",
"businessName": "Blue Sky Bakery",
"…": "every other field, as in Get Business"
},
"notice": "The Pro plan on this business is still active and billed. Cancel it in the Gogenx dashboard if it is no longer needed."
}/businesses/:id/reactivateReactivate Business
Switches a business you deactivated back on. It goes live again straight away.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
A business paused by our review team cannot be switched back on here; it answers 409 LISTING_PAUSED_BY_REVIEW.
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/reactivate" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"business": {
"id": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"status": "active",
"businessName": "Blue Sky Bakery",
"…": "every other field, as in Get Business"
}
}/businesses/:id/postsCreate Post
Writes a blog post for a business: a draft, a post scheduled for later, or one that goes live now.
| Field | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| titleRequired | string | Up to 200 characters. |
| contentHtmlRequired | string | The post, in HTML. Paragraphs, headings, lists, links, bold and italic are kept; scripts, styles and anything else are removed. |
| publish | boolean | Put the post live now. Otherwise it is saved as a draft. |
| scheduledFor | string | An ISO-8601 time in the future. The post goes live by itself then. Not together with publish. |
| coverMediaAssetId | string | The id of a post_cover image uploaded to this business with Upload Image. |
A post goes live at once and is then read by our automatic content check. Send an Idempotency-Key header to make retries safe.
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Why our sourdough rises for 18 hours",
"contentHtml": "<p>Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour.</p><h2>Come by early</h2><p>The first loaves come out of the oven at 7am.</p>",
"publish": true
}'Response · 201 Created
{
"post": {
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"title": "Why our sourdough rises for 18 hours",
"slug": "why-our-sourdough-rises-for-18-hours",
"excerpt": "Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour. Come by early The first loaves come out of the oven at 7am.",
"status": "published",
"source": "manual",
"publishTiming": "auto",
"scheduledFor": null,
"publishedAt": "2026-09-17T09:31:22.000Z",
"coverMediaAssetId": null,
"hasPendingVersion": false,
"updatedAt": "2026-09-17T09:31:22.000Z",
"contentHtml": "<p>Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour.</p><h2>Come by early</h2><p>The first loaves come out of the oven at 7am.</p>"
}
}/businesses/:id/postsList Posts
The business’s posts, newest first — the latest 100. The list leaves out each post’s contentHtml; Get Post includes it.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| Status | Type | Description |
|---|---|---|
| draft | status | Saved, not public. |
| scheduled | status | Goes live by itself at scheduledFor. |
| published | status | Live on the business’s public profile. |
| held | status | Taken down by the content check while our team looks at it. |
| generating, review | status | An AI-written post still being prepared in the dashboard. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"posts": [
{
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"title": "Why our sourdough rises for 18 hours",
"slug": "why-our-sourdough-rises-for-18-hours",
"excerpt": "Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour. Come by early The first loaves come out of the oven at 7am.",
"status": "published",
"source": "manual",
"publishTiming": "auto",
"scheduledFor": null,
"publishedAt": "2026-09-17T09:31:22.000Z",
"coverMediaAssetId": null,
"hasPendingVersion": false,
"updatedAt": "2026-09-17T09:31:22.000Z"
}
]
}/businesses/:id/posts/:postIdGet Post
One post, including its contentHtml.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| postIdRequired | path | The post id, from Create Post or List Posts. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts/01a0b2c3-589b-77bf-924f-529143527ba6" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"post": {
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"title": "Why our sourdough rises for 18 hours",
"slug": "why-our-sourdough-rises-for-18-hours",
"excerpt": "Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour. Come by early The first loaves come out of the oven at 7am.",
"status": "published",
"source": "manual",
"publishTiming": "auto",
"scheduledFor": null,
"publishedAt": "2026-09-17T09:31:22.000Z",
"coverMediaAssetId": null,
"hasPendingVersion": false,
"updatedAt": "2026-09-17T09:31:22.000Z",
"contentHtml": "<p>Every loaf rests overnight before it is baked. The long, cool rise gives the crust its crackle and the crumb its flavour.</p><h2>Come by early</h2><p>The first loaves come out of the oven at 7am.</p>"
}
}hasPendingVersion is true when an AI rewrite is waiting in the dashboard; the published words have not changed.
/businesses/:id/posts/:postIdUpdate Post
Changes the fields you send: title, contentHtml, scheduledFor or coverMediaAssetId (null removes the cover). PUT works the same way.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| postIdRequired | path | The post id, from Create Post or List Posts. |
A published post changes in place, like any blog: the new words appear on the public profile straight away and are read again by the content check. Its address (slug) does not change once it is live.
Example request
curl -X PATCH "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts/01a0b2c3-589b-77bf-924f-529143527ba6" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "title": "Why our sourdough rises for 18 hours (and why it matters)" }'Response · 200 OK
{
"post": {
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"title": "Why our sourdough rises for 18 hours (and why it matters)",
"status": "published",
"updatedAt": "2026-09-17T09:36:50.000Z",
"…": "every other field, as in Get Post"
}
}/businesses/:id/posts/:postId/publishPublish / Unpublish
Publish puts a draft or scheduled post live now. POST …/unpublish takes a published post down and makes it a draft again.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| postIdRequired | path | The post id, from Create Post or List Posts. |
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts/01a0b2c3-589b-77bf-924f-529143527ba6/publish" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"post": {
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"status": "published",
"publishedAt": "2026-09-17T09:38:12.000Z",
"…": "every other field, as in Get Post"
}
}/businesses/:id/posts/:postId/unpublishExample request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts/01a0b2c3-589b-77bf-924f-529143527ba6/unpublish" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"post": {
"id": "01a0b2c3-589b-77bf-924f-529143527ba6",
"status": "draft",
"publishedAt": null,
"…": "every other field, as in Get Post"
}
}/businesses/:id/posts/:postIdDelete Post
Deletes a post, and takes it off the public profile if it was live. This cannot be undone.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| postIdRequired | path | The post id, from Create Post or List Posts. |
Example request
curl -X DELETE "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/posts/01a0b2c3-589b-77bf-924f-529143527ba6" \
-H "Authorization: Bearer gxk_your_api_key"Response · 204 No Content
No body.
/businesses/:id/imagesUpload Image
Adds a logo, a photo or a post cover. The file itself goes straight to our storage, so uploading takes three steps.
- Ask for an upload.
POST /businesses/:id/imagesanswers with the new image and anuploadaddress. - Send the file with
PUTtoupload.url, exactly as given, with the sameContent-Type. The address works for 10 minutes. This step needs no API key and does not count as a request. - Finish.
POST /businesses/:id/images/:imageId/complete. We read the file back: a real PNG, JPG or WEBP within the size limit goes live, and anything else is refused and deleted.
| Field | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| typeRequired | string | logo (one per business, up to 2 MB), photo (up to 10, 8 MB each) or post_cover (up to 5 MB). |
| contentTypeRequired | string | image/png, image/jpeg or image/webp. |
| filename | string | The file’s name, for your own reference. |
| altText | string | A short description of the picture, for people who cannot see it. Up to 300 characters. |
| displayOrder | integer | Where a photo sits among the others, from 0. |
Step 1 · Ask for an upload
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"type": "photo",
"contentType": "image/png",
"filename": "counter.png",
"altText": "The bread counter at opening time"
}'Response · 201 Created
{
"image": {
"id": "01a0b2c3-5a21-74da-9290-e4e83a9d6257",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"type": "photo",
"status": "pending",
"contentType": null,
"byteSize": null,
"filename": "counter.png",
"altText": "The bread counter at opening time",
"displayOrder": 0,
"url": null,
"urlExpiresInSeconds": null,
"createdAt": "2026-09-17T09:32:03.000Z"
},
"upload": {
"url": "https://…r2.cloudflarestorage.com/…/listing_gallery/01a0b2c3-5a21-74da-9290-e4e83a9d6257-…?X-Amz-Signature=…",
"method": "PUT",
"headers": { "Content-Type": "image/png" },
"expiresInSeconds": 600,
"maxBytes": 8388608
}
}Step 2 · Send the file
curl -X PUT "<upload.url from step 1>" \
-H "Content-Type: image/png" \
--upload-file counter.png/businesses/:id/images/:imageId/completeStep 3 · Finish
Example request
curl -X POST "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images/01a0b2c3-5a21-74da-9290-e4e83a9d6257/complete" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"image": {
"id": "01a0b2c3-5a21-74da-9290-e4e83a9d6257",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"type": "photo",
"status": "ready",
"contentType": "image/png",
"byteSize": 1163,
"filename": "counter.png",
"altText": "The bread counter at opening time",
"displayOrder": 0,
"url": "https://…r2.cloudflarestorage.com/…/listing_gallery/01a0b2c3-5a21-74da-9290-e4e83a9d6257-…?X-Amz-Signature=…",
"urlExpiresInSeconds": 300,
"createdAt": "2026-09-17T09:32:03.000Z"
}
}To replace a logo, delete the old one first. A logo or photo is read by our automatic content check once it is live.
/businesses/:id/imagesList Images
The business’s logo, photos and post covers, in display order. Each has a url to look at it, which works for 5 minutes; ask again for a fresh one.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| type | query | Only logo, photo or post_cover. |
| Status | Type | Description |
|---|---|---|
| pending | status | Waiting for the file (steps 2 and 3). |
| ready | status | Live on the business’s profile. |
| held | status | Hidden by the content check while our team looks at it. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images?type=photo" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"images": [
{
"id": "01a0b2c3-5a21-74da-9290-e4e83a9d6257",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"type": "photo",
"status": "ready",
"contentType": "image/png",
"byteSize": 1163,
"filename": "counter.png",
"altText": "The bread counter at opening time",
"displayOrder": 0,
"url": "https://…r2.cloudflarestorage.com/…/listing_gallery/01a0b2c3-5a21-74da-9290-e4e83a9d6257-…?X-Amz-Signature=…",
"urlExpiresInSeconds": 300,
"createdAt": "2026-09-17T09:32:03.000Z"
}
]
}/businesses/:id/images/:imageIdGet Image
One image, with a fresh link to look at it.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| imageIdRequired | path | The image id, from Upload Image or List Images. |
Example request
curl "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images/01a0b2c3-5a21-74da-9290-e4e83a9d6257" \
-H "Authorization: Bearer gxk_your_api_key"Response · 200 OK
{
"image": {
"id": "01a0b2c3-5a21-74da-9290-e4e83a9d6257",
"businessId": "01a0b2c3-54d3-7d01-a6c8-566149be9778",
"type": "photo",
"status": "ready",
"contentType": "image/png",
"byteSize": 1163,
"filename": "counter.png",
"altText": "The bread counter at opening time",
"displayOrder": 0,
"url": "https://…r2.cloudflarestorage.com/…/listing_gallery/01a0b2c3-5a21-74da-9290-e4e83a9d6257-…?X-Amz-Signature=…",
"urlExpiresInSeconds": 300,
"createdAt": "2026-09-17T09:32:03.000Z"
}
}/businesses/:id/images/:imageIdUpdate Image
Changes an image’s altText (null clears it) or displayOrder. The picture itself cannot be changed; upload a new one instead.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| imageIdRequired | path | The image id, from Upload Image or List Images. |
Example request
curl -X PATCH "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images/01a0b2c3-5a21-74da-9290-e4e83a9d6257" \
-H "Authorization: Bearer gxk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "altText": "Fresh loaves on the counter", "displayOrder": 1 }'Response · 200 OK
{
"image": {
"id": "01a0b2c3-5a21-74da-9290-e4e83a9d6257",
"altText": "Fresh loaves on the counter",
"displayOrder": 1,
"…": "every other field, as in Get Image"
}
}/businesses/:id/images/:imageIdDelete Image
Deletes an image and its file, and takes it off the public profile. A post using it as its cover is left without one.
| Parameter | Type | Description |
|---|---|---|
| idRequired | path | The business id, from Create Business or List Businesses. |
| imageIdRequired | path | The image id, from Upload Image or List Images. |
Example request
curl -X DELETE "https://gogenx.ai/api/public/v1/businesses/01a0b2c3-54d3-7d01-a6c8-566149be9778/images/01a0b2c3-5a21-74da-9290-e4e83a9d6257" \
-H "Authorization: Bearer gxk_your_api_key"Response · 204 No Content
No body.
AI assistants
Connect an assistant
Manage your businesses by chatting: connect Claude or ChatGPT to Gogenx, then ask it to update your opening hours, write a post, or check how AI platforms answer about you.
https://gogenx.ai/mcpIn Claude
On the website or in the desktop app.
- Open Settings → Connectors → Add custom connector and paste the address above.
- Sign in with Gogenx when Claude opens our sign-in page, as the owner of the account.
- Read the Allow screen and press Allow. It lists what the assistant can and can never do, and where you go back to.
- Ask it something, such as “list my businesses on Gogenx”.
In ChatGPT
Paid plans only (Plus, Pro, Business, Enterprise or Education), on the website.
- Turn on Developer mode in Settings → Security and login.
- Add an app with the address above and choose OAuth for authentication.
- Sign in with Gogenx and press Allow, as in Claude.
Claude and ChatGPT sign in, so each one is listed on API & Keys in the dashboard, where Remove cuts it off at once.
In Gemini
Not yet: the Gemini app does not let you add your own connector.
In Cursor
Cursor has no connector screen in its settings, so the connection goes in a file. It uses your API key instead of signing in.
- Create or open
.cursor/mcp.jsonin your home folder — on WindowsC:\Users\<you>\.cursor\mcp.json, on a Mac~/.cursor/mcp.json— and put this in it, with your own key. - Save the file and start Cursor again.
- Open the chat with
Ctrl+Land ask “list my businesses using the gogenx tools”. Cursor asks permission to run the tool the first time.
{
"mcpServers": {
"gogenx": {
"url": "https://gogenx.ai/mcp",
"headers": { "Authorization": "Bearer gxk_your_api_key" }
}
}
}In Claude Code
One command, run in the folder you work in. Check it with claude mcp list, which should say Connected.
claude mcp add --transport http gogenx https://gogenx.ai/mcp \
--header "Authorization: Bearer gxk_your_api_key"A tool that uses your API key this way is not listed under connected assistants — it is your key, so Rotate API key stops it.
For developers of assistants
Sign-in is OAuth 2.1 as the MCP authorization specification describes: protected resource metadata at /.well-known/oauth-protected-resource/mcp, authorization server metadata at /.well-known/oauth-authorization-server, PKCE with S256, and tokens bound to https://gogenx.ai/mcp with the resource parameter. Clients may register dynamically or identify themselves with a Client ID Metadata Document. Access tokens last an hour; refresh tokens are replaced each time they are used.
AI assistants
What it can do
A connected assistant acts as the owner who connected it, through the same rules as the dashboard. It asks you before it changes anything.
| Tool | Type | Description |
|---|---|---|
| list_businesses | read | Your businesses, with status, plan and city. |
| get_business | read | Every detail of one business. |
| get_ai_visibility | read | The latest check of how AI platforms answer about the business (Pro and Scale). |
| get_directory_listings | read | Where the business is listed on the Gogenx directory network (Pro and Scale). |
| list_posts, get_post | read | The business’s blog posts. |
| list_categories | read | Find category codes by name. |
| update_business | change | Change business details, opening hours and FAQs. |
| create_post, update_post | change | Write a post (saved as a draft) or edit one. |
| publish_post | change | Put a post live. |
Never available to an assistant: billing, plans or payments; deleting or deactivating a business; creating a business or sending one for review; your account, sign-in or team. Those stay in the dashboard.
Each tool call counts as one of your account’s 10,000 monthly requests. Posts and changes an assistant makes are read by the content check like any other, and your business history records them as made by an AI assistant.
Reference
Business fields
Every field of a business, as Create Business and Update Business accept it and Get Business returns it.
About the business
| Field | Type | Description |
|---|---|---|
| businessNameRequired | string | The name customers know. Up to 200 characters. |
| legalEntityName | string | The registered name, if different. |
| shortDescription | string | One line, up to 300 characters. A description or short description is required. |
| description | string | The full description, up to 5,000 characters. |
| primaryCategoryCodeRequired | string | The main category, a code from Categories. |
| additionalCategoryCodes | string[] | Up to 4 more category codes. |
| industryVertical | string | The wider industry, up to 80 characters. |
| yearEstablished | integer | From 1800 to this year. |
| teamSize | string | For example "2-10". |
| numberOfEmployees | integer | How many people work there. |
| priceRange | string | $, $$, $$$ or $$$$. |
| mission | string | Up to 2,000 characters. |
| uniqueValueClaims | string | What sets the business apart, up to 2,000 characters. |
| businessSizeTarget | string | The size of customer it serves. |
| targetAudienceDescription | string | Who it serves, up to 1,000 characters. |
Contact
| Field | Type | Description |
|---|---|---|
| publicPhoneRequired | string | The public number, for example +1 512 555 0142. |
| mobilePhone | string | A mobile number. |
| publicEmail | string | The public email address. |
| website | string | A full address, starting https://. |
| bookingUrl, menuUrl, googleMapsUrl | string | Where to book, the menu, and the business on Google Maps. |
| contactFirstNameRequired | string | The person we contact about this business. |
| contactLastNameRequired | string | Their last name. |
| businessContactEmailRequired | string | Where we contact the business. |
Location
| Field | Type | Description |
|---|---|---|
| streetAddressRequired | string | Up to 240 characters. |
| cityRequired | string | Up to 120 characters. |
| stateRegionRequired | string | State, province or region. |
| postalCodeRequired | string | Checked against the country’s format. Not required in countries without postal codes. |
| countryCodeRequired | string | Two-letter ISO code, for example US or GB. |
| latitude, longitude | number | The map pin for the front door. |
| timezone | string | An IANA name, for example America/Chicago. |
| serviceArea | string | Where the business serves customers, up to 500 characters. |
Details
| Field | Type | Description |
|---|---|---|
| hours | object | Opening hours — see below. |
| faqs | object[] | Questions an AI assistant should be able to answer about the business: { question, answer }. Up to 5 on a Free business, 25 on Pro and Scale. |
| services | object[] | Up to 50: { name, description, priceMinor, currency, priceNote }. Only name is required. priceMinor is in the currency’s smallest unit — 4500 with USD is $45.00. |
| keywords | string[] | Up to 50 search terms. |
| attributes | string[] | Up to 40, for example "Wheelchair accessible". |
| languages | string[] | Up to 20, as names ("Spanish") or codes ("es"). |
| paymentMethodLabels | string[] | Up to 20 ways to pay. |
| socialProfiles | object | { profiles: [{ provider, url }] }, up to 12. provider is instagram, facebook, tiktok, x, linkedin or pinterest. |
| brandColors | string[] | Up to 6 hex colours, for example #ff6b35. |
| brandColorUsageNote | string | How the colours are used. |
Set by Gogenx
| Field | Type | Description |
|---|---|---|
| id | string | The business’s permanent id. |
| status | string | draft, submitted, under_review, active (live), rejected (sent back — fix and submit again) or paused (deactivated, or paused by our review team). |
| plan | string | free, pro or scale. Changed in the dashboard. |
| submittedAt, activatedAt, createdAt, updatedAt | string | ISO-8601 times in UTC. |
The plan, billing cycle, tax number and internal notes are only entered in the dashboard; sending them is refused with a message saying so.
Opening hours
Each day is mon to sun, with closed and up to 4 intervals for split hours, in 24-hour HH:MM. A day left out has no hours given.
{
"hours": {
"days": {
"mon": { "closed": false, "intervals": [{ "open": "07:00", "close": "15:00" }] },
"sat": {
"closed": false,
"intervals": [{ "open": "08:00", "close": "12:00" }, { "open": "13:00", "close": "16:00" }]
},
"sun": { "closed": true, "intervals": [] }
}
}
}/categoriesCategories
The category codes for primaryCategoryCode and additionalCategoryCodes. No API key is needed, and it does not count toward your requests.
Example request
curl "https://gogenx.ai/api/public/v1/categories"Response · 200 OK
{
"categories": [
{ "code": "bakeries", "label": "Bakeries" },
{ "code": "coffee-houses-and-tea-rooms", "label": "Coffee Houses and Tea Rooms" },
{ "code": "restaurants", "label": "Restaurants" }
]
}Reference
Content check
Posts, logos, photos and post covers go live straight away, and our automatic check reads them just after. So do edits to a live business’s details.
- A post or image the check flags is taken down at once. It reads back with
"status": "held"and anoticeexplaining why, and our team decides whether it goes back up. - A held post cannot be changed or published until they finish (
409 POST_HELD_FOR_REVIEW). You can still delete it. - If our team restores it, it goes back up exactly as it was. If they remove it, it is gone for good.
- A flagged change to a business’s details stays live while our team looks at it; they may pause the business.
Reference
Safe retries
If a request times out, you cannot tell whether it worked. Send an Idempotency-Key header on Create Business and Create Post, and retrying is safe.
- Use a unique value per thing you create, for example your own record’s id.
- Sent again with the same key and body within 24 hours, the request is not repeated: you get the first answer, with the header
Idempotent-Replay: true. - The same key with a different body is refused with
409 IDEMPOTENCY_KEY_REUSED. - A request that failed can be corrected and sent again with the same key.
Reference
Error Codes
Every error has the same shape: a code to act on, a message to show a person, details naming fields where that helps, and a requestId to quote if you contact us.
Example · 401 Unauthorized
{
"error": {
"code": "UNAUTHENTICATED",
"message": "An API key is required. Send it as: Authorization: Bearer <key>",
"requestId": "req_8f14e45f-ceea-467a-9575-5a3c1c2f3a1b",
"details": []
}
}| Status | Code | What it means |
|---|---|---|
| 400 | VALIDATION_FAILED | A field is the wrong type or too long, a field name is not recognised, or a value is out of range. details names each field. |
| 400 | LISTING_INCOMPLETE | Create Business or Submit for Review is missing required details. Nothing was created; details lists every missing field. |
| 400 | UNKNOWN_CATEGORY | A category code is not in Categories. |
| 401 | UNAUTHENTICATED | No API key, or a key that is wrong or has been rotated. |
| 402 | PLAN_LIMIT_REACHED | More FAQs than the business’s plan allows (5 on Free, 25 on Pro and Scale). |
| 403 | API_KEY_OWNER_GONE | The person who made the key is no longer the account’s owner. Make a new key in the dashboard. |
| 404 | BUSINESS_NOT_FOUND | Not a business on this account. Another account’s business answers the same. |
| 404 | POST_NOT_FOUND | Not a post of this business. |
| 404 | IMAGE_NOT_FOUND | Not an image of this business. |
| 409 | LISTING_NOT_LIVE | Only a live (active) business can be deactivated. |
| 409 | LISTING_NOT_DEACTIVATED | Reactivate only switches back on a business you deactivated. |
| 409 | LISTING_PAUSED_BY_REVIEW | Our review team paused this business. Contact support. |
| 409 | LISTING_INVALID_STATE | The business cannot do that from its current status, for example submitting one that is already live. |
| 409 | POST_HELD_FOR_REVIEW | The post is being checked by our team and cannot be changed yet. See Content check. |
| 409 | POST_ALREADY_PUBLISHED | The post is already published. |
| 409 | POST_NOT_PUBLISHED | The post is not published, so there is nothing to take down. |
| 409 | IMAGE_LIMIT_REACHED | The business already has its logo, or its 10 photos. Delete one first. |
| 409 | MEDIA_NOT_UPLOADED | Complete was called before the file was sent to the upload URL. |
| 409 | MEDIA_HELD_FOR_REVIEW | The image is being checked by our team and cannot be used as a cover yet. |
| 409 | IDEMPOTENCY_KEY_REUSED | The same Idempotency-Key was sent with a different body. |
| 409 | IDEMPOTENCY_IN_PROGRESS | The first request with this Idempotency-Key is still running. Retry shortly. |
| 413 | MEDIA_TOO_LARGE | The file is over the size limit for its type. It was deleted. |
| 422 | MEDIA_REJECTED | The file is not a PNG, JPG or WEBP image. It was deleted. |
| 422 | MEDIA_EMPTY | The file was empty. It was deleted. |
| 429 | API_QUOTA_EXCEEDED | This month’s 10,000 requests are used. The message gives the reset date. |
| 429 | RATE_LIMITED | Over 120 requests in a minute with one key. Wait a moment and retry. |
| 500 | INTERNAL_ERROR | Our fault. Retry; if it continues, send us the requestId. |