/developer/* for developer-account-scoped operations (building and publishing apps) and /admin/* for merchant-scoped operations (installing apps, managing webhooks and API keys from within a store).
Base URL https://api.genuka.com · Auth Authorization: Bearer <token> + X-Company: <companyId> · Getting Started
Endpoints at a glance
Developer Auth
These endpoints use thedeveloper guard (Laravel Sanctum). They do not require X-Company header.
GET /2023-11/developer/auth/login
No-op endpoint — returns a redirect placeholder for the login form. Not useful for API clients.
Success response (200 OK): HTML redirect or empty body.
POST /2023-11/developer/auth/login
Authenticate a developer account and return a Sanctum access token.
Request body
200 OK):
401—{ "message": "Invalid email or password." }
POST /2023-11/developer/auth/logout
Revoke the current developer access token and its refresh token.
Request body: None — authentication is performed via the Authorization: Bearer <token> header only.
200 OK):
401—{ "message": "Unauthenticated." }
GET /2023-11/developer/auth/register
No-op endpoint — redirect placeholder. Not useful for API clients.
POST /2023-11/developer/auth/register
Register a new developer account. Creates both a Company (type=developer) and a Developer user, then issues a Sanctum token.
Request body
200 OK):
400—{ "message": "Company payload is required" }400—{ "message": "User with given email already exists. Please login" }
POST /2023-11/developer/auth/password/email
Send a password-reset link to a developer email address.
Request body
200 OK):
400—{ "message": "We can't find a user with that email address." }422—{ "message": "The given data was invalid.", "errors": { "email": ["The email field is required."] } }
POST /2023-11/developer/auth/password/reset
Reset developer password using the token from the reset email.
Request body
200 OK):
400—{ "message": "This password reset token is invalid." }
Developer Profile
GET /2023-11/developer/me
Get the authenticated developer’s profile including company stats.
200 OK):
401—{ "message": "Unauthenticated." }
DELETE /2023-11/developer/me/delete
Permanently delete the authenticated developer account. All Passport tokens are revoked first.
200 OK):
401—{ "message": "Unauthenticated." }
PUT /2023-11/developer/me/metadata
Merge arbitrary key-value pairs into the developer’s metadata JSON column. Existing keys not in the request are preserved.
Request body: Any flat JSON object. All top-level keys (except the reserved keys metadata and anonymous) are merged into the stored metadata object. There is no fixed schema — send any key-value pairs your application needs.
200 OK): Returns the updated developer user resource.
401—{ "message": "Unauthenticated." }
Apps (Developer)
GET /2023-11/developer/apps
List apps. Developer-type companies see only their own apps. Business-type companies see only published apps. Super-admins see all.
Query parameters
200 OK):
401—{ "message": "Unauthenticated." }
POST /2023-11/developer/apps
Create a new app. A Passport OAuth client is automatically created and the client_id/client_secret are returned (the only time the secret is shown in full).
Request body
200 OK): App object with client_secret shown in full (only revealed at creation time).
400—{ "error": "The name has already been taken." }422—{ "message": "The given data was invalid.", "errors": { "name": ["The name field is required."] } }
GET /2023-11/developer/apps/{app}
Get details of a single app.
Path parameters
200 OK):
404—{ "message": "No query results for model." }
PUT /2023-11/developer/apps/{app}
Update an existing app. Only fields provided are updated. Pass regenerate_keys: true to rotate the OAuth client ID and secret.
Path parameters
Request body
200 OK): Updated app resource.
400—{ "error": "..." }404—{ "message": "No query results for model." }
DELETE /2023-11/developer/apps/{app}
Delete an app. Only allowed when status is draft and the calling user has the admin role in the owning company.
Path parameters
200 OK):
403—{ "error": "App does not belong to the company" }403—{ "error": "App is not in draft status" }403—{ "error": "You are not authorized to delete this app" }
GET /2023-11/developer/apps/{app}/secret
Reveal the full client_secret for an app. The secret is masked (•••) in all other responses.
Path parameters
200 OK): App resource with client_secret in plaintext.
404—{ "message": "No query results for model." }
PATCH /2023-11/developer/apps/{app}/status
Change the lifecycle status of an app. Moving to pending records submitted_at; moving to published records published_at and triggers an email notification to the developer admin.
Path parameters
Request body
200 OK): Updated app resource.
422—{ "message": "The given data was invalid.", "errors": { "status": ["..."] } }
App Reviews
GET /2023-11/developer/apps-reviews and GET /2023-11/admin/apps-reviews
List app reviews. Developer-company users see reviews for their own apps only; super-admins see all.
Query parameters
200 OK): Paginated list of review objects.
POST /2023-11/developer/apps-reviews and POST /2023-11/admin/apps-reviews
Create a new review record for an app.
Request body
201 Created): Review object with app and reviewer relations loaded.
GET /2023-11/developer/apps-reviews/{reviewId} and GET /2023-11/admin/apps-reviews/{reviewId}
Get a single review with its related app.
Path parameters
Success response (
200 OK): Review object with app loaded.
PUT /2023-11/developer/apps-reviews/{reviewId} and PUT /2023-11/admin/apps-reviews/{reviewId}
Update an existing review.
Path parameters
Request body
Success response (
200 OK): Updated review with app and reviewer.
DELETE /2023-11/developer/apps-reviews/{reviewId} and DELETE /2023-11/admin/apps-reviews/{reviewId}
Delete a review.
Path parameters
Success response (
200 OK):
App Shortcuts
App shortcuts are deep-link entries injected into the merchant dashboard UI by an installed app.GET /2023-11/developer/app-shortcuts
List app shortcuts. Results are filtered by the authenticated company via query filters.
Query parameters
200 OK): Paginated list of app shortcut objects.
POST /2023-11/developer/app-shortcuts
Create an app shortcut.
Request body
201 Created): App shortcut resource object.
GET /2023-11/developer/app-shortcuts/{appShortcut}
Get a single shortcut. Only returned if the shortcut belongs to the requesting company.
Path parameters
Success response (
200 OK): Shortcut resource object.
404—{ "error": "App shortcut not available for this company" }
PUT /2023-11/developer/app-shortcuts/{appShortcut}
Update a shortcut. Only available if the shortcut belongs to the requesting company.
Path parameters
Request body
200 OK): Updated shortcut resource.
404—{ "error": "App shortcut not available for this company" }
DELETE /2023-11/developer/app-shortcuts/{appShortcut}
Delete a shortcut.
Path parameters
Success response (
200 OK):
404—{ "error": "App shortcut not available for this company" }
OAuth 2.0
The Genuka OAuth flow allows apps to act on behalf of a merchant company. The flow is:- Initiate — app calls
/oauth/initiatewith itsclient_idto get a short-livedrequest_code. - Authorize — merchant user approves in the dashboard, which calls
/oauth/authorize. On approval, an authorization code is generated and the callback URL receives an HMAC-signed redirect. - Exchange — app exchanges the
codefor an access token (see the OAuth token exchange endpoint, not listed separately here; call/2023-11/admin/apps/oauth/tokendirectly with client credentials). - Refresh — call
/oauth/refreshwith the refresh token to rotate credentials.
POST /2023-11/developer/apps/oauth/initiate and POST /2023-11/admin/apps/oauth/initiate
Begin the authorization flow. Returns a request_code that the app should pass to the authorization UI.
Request body
200 OK):
POST /2023-11/developer/apps/oauth/authorize and POST /2023-11/admin/apps/oauth/authorize
Approve or deny an authorization request. On approval, creates or updates an AppInstall record, generates an auth code, and returns the signed redirect URL that the frontend should follow.
Requires the requesting company to have an active subscription if the app has a non-zero price.
Request body
200 OK):
400—{ "error": "Invalid company" }400—{ "error": "Invalid app" }200—{ "message": "Authorization denied" }(whenapproved: falseor subscription missing)
POST /2023-11/developer/apps/oauth/refresh and POST /2023-11/admin/apps/oauth/refresh
Exchange a refresh token for new access and refresh tokens.
Request body
200 OK):
400—{ "error": "Invalid or expired refresh token" }
Apps (Admin / Merchant)
GET /2023-11/admin/apps
List apps visible to the merchant. Business-company users see published apps only; super-admins see all.
Same query parameters as GET /2023-11/developer/apps.
Success response (200 OK):
GET /2023-11/admin/apps/{app}
Get a single app (merchant view).
Path parameters
Success response (
200 OK): App resource.
PATCH /2023-11/admin/apps/{app}/status
Update app status. For platform admins / super-admins to publish, reject, or archive apps.
Path parameters
Request body
200 OK): Updated app resource.
POST /2023-11/admin/apps/subscribe
Subscribe a company to an app plan. Initiates payment via Stripe or PawaPay and returns a redirect URL to the payment page.
Request body
200 OK):
400—{ "message": "Payment URL unavailable", "payment_method": "stripe" }422— validation errors
Installed Apps
GET /2023-11/admin/apps-installed
List all app installations for the current company.
Query parameters
200 OK):
GET /2023-11/admin/apps-installed/{appInstall}
Get a single installation. Also returns a signed redirect_url that the app can use to open the merchant’s store context.
Path parameters
200 OK):
404—{ "error": "App not installed by the company" }
DELETE /2023-11/admin/apps-installed/{appInstall}
Uninstall an app from the company. Dispatches a webhook notification to the app’s webhook_url if configured.
Path parameters
200 OK):
404—{ "error": "App not installed by the company" }
API Keys
API keys allow programmatic access to the Genuka API without OAuth. Only users with theadmin, manager, or superadmin role can list keys.
GET /2023-11/admin/apikeys
List API keys.
Query parameters
200 OK): Paginated list of API key objects.
401—{ "error_code": "UNAUTHORIZED", "message": "You are not authorized to list apikeys.", "role": "..." }
POST /2023-11/admin/apikeys
Create a new API key. The key value is randomly generated (32 characters). Expires in one year by default.
Request body
200 OK): API key resource — includes the key value; store it immediately as it is not re-displayable.
DELETE /2023-11/admin/apikeys/{apikey}
Permanently delete an API key.
Path parameters
200 OK):
Webhooks
Webhooks let your app receive real-time POST notifications when business events occur. Genuka signs each delivery with an HMAC-SHA256 signature using the webhook’ssecret. The secret is only returned at creation time and after a regeneration.
Webhooks are automatically disabled after 10 consecutive delivery failures.
Available events
Events follow the pattern{resource}.{action}. Resources include: delivery, order, customer, invoice, payment, address, shop, product, product_variant, stock, stock_warehouse, supplier, supplier_product, tag, taggable, user, tax, discount, pickup_location, shipping_fee, warehouse, transfer, order_product, product_return, service, campaign, campaign_template, campaign_customer, inbox_conversation, inbox_message. Actions for most resources: created, updated, deleted, restored.
GET /2023-11/admin/webhooks
List webhooks for the current company.
Query parameters
200 OK):
Note: secret is hidden in list and show responses. It is only returned when the webhook is first created or the secret is regenerated.
GET /2023-11/admin/webhooks/count
Return the total number of webhooks for the current company.
200 OK):
POST /2023-11/admin/webhooks
Create a new webhook. The signing secret (32 random characters) is generated automatically and included in the response once only.
Request body
201 Created):
422—{ "message": "The given data was invalid.", "errors": { "url": ["The URL must use the HTTPS protocol"], "events": ["At least one event must be selected"] } }
GET /2023-11/admin/webhooks/{webhook}
Get a single webhook.
Path parameters
Success response (
200 OK): Webhook resource (secret hidden).
404—{ "message": "Webhook not found" }
PUT /2023-11/admin/webhooks/{webhook}
Update a webhook’s URL, events, description, or active state.
Path parameters
Request body
200 OK): Updated webhook resource.
404—{ "message": "Webhook not found" }422— validation errors
DELETE /2023-11/admin/webhooks/{webhook}
Delete (soft-delete) a webhook.
Path parameters
Success response (
200 OK): Deleted webhook resource.
404—{ "message": "Webhook not found" }
PATCH /2023-11/admin/webhooks/{webhook}/toggle
Toggle the is_active flag on a webhook. Also resets the failure_count to 0.
Path parameters
Request body: None — no body required for this action endpoint.
200 OK): Updated webhook resource with toggled is_active.
404—{ "message": "Webhook not found" }
POST /2023-11/admin/webhooks/{webhook}/test
Send a test event payload to the webhook URL. Useful for verifying connectivity.
Path parameters
Request body: None — the test payload is constructed automatically from the stored webhook record (id, company_id, secret).
200 OK):
404—{ "message": "Webhook not found" }500—{ "message": "Error sending test webhook", "error": "..." }
PATCH /2023-11/admin/webhooks/{webhook}/regenerate-secret
Generate a new signing secret for the webhook. Resets failure_count to 0. The new secret is returned in the response — update your HMAC verification logic accordingly.
Path parameters
Request body: None — no body required for this action endpoint.
200 OK): Webhook resource with new secret visible.
Payment Methods
GET /2023-11/developer/payment-methods
List payment methods for the company.
Query parameters
200 OK): Paginated list of payment method objects.
POST /2023-11/developer/payment-methods
Create a new payment method (or update the existing one for the same processor). Also creates a linked treasury account if none exists.
Request body
201 Created): Payment method resource.
400—{ "message": "Invalid payment processor" }500—{ "message": "An error occurred while creating the payment method" }
GET /2023-11/developer/payment-methods/{paymentMethod}
Get a single payment method.
Path parameters
Success response (
200 OK): Payment method resource.
PUT /2023-11/developer/payment-methods/{paymentMethod}
Update a payment method’s account_id, status, metadata, and configurations.
Path parameters
Request body
Success response (
200 OK): Updated payment method resource.
DELETE /2023-11/developer/payment-methods/{paymentMethod}
Delete a payment method.
Path parameters
Success response (
204 No Content): Empty body.
GET /2023-11/developer/payment-methods/stripe/connect
Initiate Stripe Connect OAuth. Returns the Stripe OAuth authorization URL the user should be redirected to.
200 OK):
POST /2023-11/developer/payment-methods/stripe/direct-keys
Save direct Stripe integration keys (publishable key, secret key, webhook signing secret). Validates the secret key against Stripe before saving. Switches the integration mode to direct.
Request body
200 OK):
422—{ "message": "Invalid Stripe secret key." }422—{ "message": "Could not validate Stripe credentials: ..." }
GET /2023-11/developer/payment-methods/stripe/webhook-url
Get the Stripe webhook endpoint URL to register in the Stripe dashboard for direct-mode merchants.
200 OK):
File Uploads (S3)
Genuka uses a two-step upload pattern: first obtain a presigned URL, then PUT directly to S3. For large files, use the multipart flow.POST /2023-11/developer/upload/presign
Generate a presigned S3 PUT URL for single-file upload.
Request body
200 OK):
key in the medias[].s3_key field when creating or updating the model.
POST /2023-11/developer/upload/multipart/create
Create a multipart upload and get presigned URLs for all parts.
Request body
200 OK):
POST /2023-11/developer/upload/multipart/complete
Complete a multipart upload after all parts have been PUT to S3.
Request body
200 OK): S3 CompleteMultipartUpload result.
POST /2023-11/developer/upload/multipart/abort
Abort an in-progress multipart upload.
Request body
200 OK):
DELETE /2023-11/developer/upload/by-key
Delete an S3 object by its key. Only keys under company/{companyId}/ are permitted.
Request body
200 OK):
403—{ "message": "Unauthorized key prefix" }
Wallets & Withdrawals
GET /2023-11/developer/wallets
List wallet transaction ledger entries for the developer’s company.
Query parameters
200 OK): Paginated wallet entries.
422—{ "message": "User is not linked to any company." }
POST /2023-11/developer/withdraw
Submit a withdrawal request against the company wallet balance. Only one pending request is allowed at a time.
Request body
201 Created):
422—{ "message": "Insufficient wallet balance." }422—{ "message": "You already have a withdraw request in progress." }
GET /2023-11/developer/withdraw/withdraw-requests
List all withdrawal requests for the developer’s company.
Query parameters
200 OK): Paginated withdraw requests.
status values: pending, approved, rejected.