Skip to main content
Question

REST Login Headers

  • July 29, 2025
  • 33 replies
  • 374 views

JSpikowski
Jr Varsity II
Forum|alt.badge.img

I was testing the Login endpoint in ScriptBasic with cURL and I’m seeing duplicate Set-Cookie: headers returned. Can someone in the development group check to see if they are sending dups?

 

C:\Acumatica>sbc login.sb
HTTP/1.1 204 No Content
Cache-Control: private
Set-Cookie: ASP.NET_SessionId=fzij23u0gpn1ytgyppfvk5re; path=/; HttpOnly; SameSite=Lax
Set-Cookie: UserBranch=16; path=/
Set-Cookie: Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Fri, 01-Aug-2025 03:44:56 GMT; path=/
Set-Cookie: CompanyID=Demo; expires=Fri, 01-Aug-2025 03:44:56 GMT; path=/
Set-Cookie: .ASPXAUTH=3E6A8CF7C56FAF5905F956EE5ABB7B17872218E74715D89CB07F22DB2F7FFC7D3DE46736133B9E1A9BFC40CD97D90287B59FCA47ABBEBA08EA1AEABE8B087BB07B41920C18FA22437784124D3FEF3092B636BFB4343575ED04610B1553C710A56C20661E011FCF4F9B31F3D0ECC9D4AFE14B125D1CDFF22CD34BEB30E019593E81EC0885; path=/; HttpOnly
Set-Cookie: ASP.NET_SessionId=fzij23u0gpn1ytgyppfvk5re; path=/; HttpOnly; SameSite=Lax
Set-Cookie: UserBranch=16; path=/
Set-Cookie: Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Fri, 01-Aug-2025 03:44:56 GMT; path=/
Set-Cookie: CompanyID=Demo; expires=Fri, 01-Aug-2025 03:44:56 GMT; path=/
Set-Cookie: .ASPXAUTH=3E6A8CF7C56FAF5905F956EE5ABB7B17872218E74715D89CB07F22DB2F7FFC7D3DE46736133B9E1A9BFC40CD97D90287B59FCA47ABBEBA08EA1AEABE8B087BB07B41920C18FA22437784124D3FEF3092B636BFB4343575ED04610B1553C710A56C20661E011FCF4F9B31F3D0ECC9D4AFE14B125D1CDFF22CD34BEB30E019593E81EC0885; path=/; HttpOnly
Set-Cookie: requestid=A90D684CE00086AF11F06C2E63B6A149; path=/
Set-Cookie: requeststat=+st:1064+sc:~/entity/auth/login+start:638893574955694025+tg:; path=/
Date: Tue, 29 Jul 2025 03:44:57 GMT

 

C:\Acumatica>

33 replies

JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 29, 2025

RFC 6265 (HTTP State Management Mechanism): advises against this, stating that "Servers SHOULD NOT include more than one Set-Cookie header field in the same response with the same cookie-name." 

While browsers might process duplicate Set-Cookie headers for the same cookie, it is best practice for servers to avoid sending them to ensure consistent and predictable behavior across different user agents and to prevent potential issues.

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 29, 2025

I haven't tried this but sounds like a good workaround.

You can add the following key in the AppSettings in the web config file it solves the issue of duplicate cookie.

<!-- Tell ASPNET to avoid duplicate Set-Cookies on the Response Headers-->
<appSettings>
<add key="aspnet:AvoidDuplicatedSetCookie" value="true" />
</appSettings>

This will help avoiding the duplicate Set-Cookie() in Response Headers.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 29, 2025

I wrote a routine that converts the raw Set-Cookie headers to an associative array to eliminate the duplicates. The output shows the cookie key and the complete header string.

CODE

IMPORT curl.sbi

jstr = """
{
"name": "admin",
"password": "PASSWORD",
"company": "Demo"
}
"""

ch = curl::init()
url = "http://localhost/acumaticadb/entity/auth/login"
curl::option(ch, "URL", url)
curl::option(ch, "HEADER")
curl::option(ch, "HTTPHEADER", "Content-Type: application/json")
curl::option(ch, "POSTFIELDS", jstr)

response_headers = curl::perform(ch)

curl::finish(ch)

' PRINT json, "\n"

SPLITA response_headers BY "\n" TO headers
FOR x = 0 TO UBOUND(headers) -1
IF LEFT(headers[x], 11) = "Set-Cookie:" THEN
p1 = INSTR(headers[x], " ")
tmpstr = MID(headers[x], p1 + 1)
p2 = INSTR(tmpstr, "=")
key = LEFT(tmpstr, p2 -1)
new_header{key} = tmpstr
END IF
NEXT

FOR i = 0 TO UBOUND(new_header) STEP 2
PRINT new_header[i], " - ", new_header[i + 1], "\n"
NEXT

END

OUTPUT

C:\Acumatica>sbc login.sb
ASP.NET_SessionId - ASP.NET_SessionId=suoupjb1brq5zvdc3nftdfro; path=/; HttpOnly; SameSite=Lax
UserBranch - UserBranch=16; path=/
Locale - Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Fri, 01-Aug-2025 22:26:25 GMT; path=/
CompanyID - CompanyID=Demo; expires=Fri, 01-Aug-2025 22:26:25 GMT; path=/
.ASPXAUTH - .ASPXAUTH=1726125EC2AB4E7E249D26E8FCE34DC4BA6D18BFBBF05BA3D1E172224B78C6D724A802F4CF31D61C1E81533299BFCCB3ADD2DB51D59043A315E1AA1C2805A83C880C1F60DB9C8FBDEC3AB637EC0492C96EAD764FBE245E162D9430BDD9D1D951C1C59DB157FDB8FD874FDB7F6454B0CB769BD7203F7A4F3AEA1E05CFC3C8C596B1C4412B; path=/; HttpOnly
requestid - requestid=A90D684CE00086AF11F06CCB0F59E2D4; path=/
requeststat - requeststat=+st:486+sc:~/entity/auth/login+start:638894247850195284+tg:; path=/

C:\Acumatica>

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 29, 2025

I posted a fix  to the duplicate header issue with a code example. After posting it said the post needed to approved by the forum moderator. Do posts that include code have to be approved or has my forum status been changed?


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

This example gets the Login endpoint Set-Cookie headers, eliminates the duplicates and formats them to be used in the Customer endpoint.Cookie: header. The script displays the Set-Cookie list from the associative array, then does a Customer endpoint by customer ID using the formatted Cookie: header. I convert the response to a ScriptBasic associative array and dump the array in formatted output.

CODE

IMPORT curl.sbi
IMPORT webext.sbi

jstr = """
{
"name": "admin",
"password": "WordPass52!",
"company": "Demo"
}
"""

ch = curl::init()
url = "http://localhost/acumaticadb/entity/auth/login"
curl::option(ch, "URL", url)
curl::option(ch, "HEADER")
curl::option(ch, "HTTPHEADER", "Content-Type: application/json")
curl::option(ch, "POSTFIELDS", jstr)

response_headers = curl::perform(ch)

curl::finish(ch)

SPLITA response_headers BY "\n" TO headers
FOR x = 0 TO UBOUND(headers) -1
IF LEFT(headers[x], 11) = "Set-Cookie:" THEN
p1 = INSTR(headers[x], " ")
tmpstr = MID(headers[x], p1 + 1)
p2 = INSTR(tmpstr, "=")
key = LEFT(tmpstr, p2 -1)
new_header{key} = tmpstr
END IF
NEXT

FOR i = 0 TO UBOUND(new_header) STEP 2
PRINT new_header[i], " - ", new_header[i + 1], "\n"
NEXT

PRINT "\n"

ch = curl::init()
url = "http://localhost/acumaticadb/entity/Default/24.200.001/Customer/ABARTENDE"
curl::option(ch, "URL", url)
curl::option(ch, "HTTPHEADER", "Content-Type: application/x-www-form-urlencoded")
curl::option(ch, "HTTPHEADER", "Cookie: " & _
LEFT(new_header{".ASPXAUTH"}, INSTR(new_header{".ASPXAUTH"},";")) & " " & _
LEFT(new_header{"ASP.NET_SessionId"}, INSTR(new_header{"ASP.NET_SessionId"}, ";")) & " " & _
LEFT(new_header{"CompanyID"}, INSTR(new_header{"CompanyID"}, ";")) & " " & _
LEFT(new_header{"Locale"}, INSTR(new_header{"Locale"}, ";")) & " " & _
LEFT(new_header{"UserBranch"}, INSTR(new_header{"UserBranch"}, ";")) & " " & _
LEFT(new_header{"requestid"}, INSTR(new_header{"requestid"}, ";")) & " " & _
LEFT(new_header{"requeststat"}, INSTR(new_header{"requeststat"}, ";")))
json = curl::perform(ch)
curl::finish(ch)

web::json2sba(json)
web::sbadump(json, 1)

END

OUTPUT

C:\Acumatica>sbc login.sb
ASP.NET_SessionId - ASP.NET_SessionId=1z3cx2q0rzgt3qrjjhgydhi5; path=/; HttpOnly; SameSite=Lax
UserBranch - UserBranch=16; path=/
Locale - Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Sat, 02-Aug-2025 00:46:00 GMT; path=/
CompanyID - CompanyID=Demo; expires=Sat, 02-Aug-2025 00:46:00 GMT; path=/
.ASPXAUTH - .ASPXAUTH=26F6232A84CEB4DF7ADB4FF5AF217841013E270BC5AF044670EB32CC1023320618C402C7EFA8FB88AF90C2CC1D35379E85C96E3872B048A916CEFB0F9E786E6A7E7ECC084032C5BD9906BAC71396461E87CCE21008D8B434394B6C581CBABAC1EF4D931A18901405169E00241102D9FAA0C77ABCC7BDBEDF93743E14CEE1CF826D93C9CC; path=/; HttpOnly
requestid - requestid=A90D684CE00086AF11F06CDE8F36CC2B; path=/
requeststat - requeststat=+st:390+sc:~/entity/auth/login+start:638894331599757995+tg:; path=/

id = 6a113b2c-d87f-e411-beca-00b56d0561c2
rowNumber = 1
note
   value =
ApplyOverdueCharges
   value = FALSE
AutoApplyPayments
   value = FALSE
BAccountID
   value = 4899
BillingAddressOverride
   value = TRUE
BillingContactOverride
   value = TRUE
CreatedDateTime
   value = 2023-12-31T16:00:00-08:00
CreditLimit
   value = 0
CurrencyID
   value = USD
CustomerCategory
   value = I
CustomerClass
   value = KEY
CustomerID
   value = ABARTENDE
CustomerName
   value = USA Bartending School
Email
   value = barkeep@usabartend.con
EnableCurrencyOverride
   value = TRUE
EnableRateOverride
   value = FALSE
EnableWriteOffs
   value = TRUE
EntityUsageType
   value = Default
LastModifiedDateTime
   value = 2023-12-31T16:00:00-08:00
LeadTimedays
   value = 0
LocationName
   value = Primary Location
MultiCurrencyStatements
   value = FALSE
NoteID
   value = 6a113b2c-d87f-e411-beca-00b56d0561c2
OrderPriority
   value = 10
PrimaryContactID
   value = 9977
PrintDunningLetters
   value = FALSE
PrintInvoices
   value = FALSE
PrintStatements
   value = FALSE
ResidentialDelivery
   value = FALSE
RestrictVisibilityTo
   value = PROD
SaturdayDelivery
   value = FALSE
SendDunningLettersbyEmail
   value = TRUE
SendInvoicesbyEmail
   value = TRUE
SendStatementsbyEmail
   value = FALSE
ShippingAddressOverride
   value = TRUE
ShippingContactOverride
   value = TRUE
ShippingRule
   value = Back Order Allowed
ShippingTerms
   value = CFR
StatementCycleID
   value = EOM
StatementType
   value = Open Item
Status
   value = Active
Terms
   value = 30D
WriteOffLimit
   value = 20
_links
   self = /acumaticadb/entity/Default/24.200.001/Customer/6a113b2c-d87f-e411-beca-00b56d0561c2
   files:put = /acumaticadb/entity/Default/24.200.001/files/PX.Objects.AR.CustomerMaint/BAccount/6a113b2c-d87f-e411-beca-00b56d0561c2/{filename}

C:\Acumatica>


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

When doing REST API calls, cookies really don't make sense as there is no browser involved. Grabbing Set-Cookie headers and converting them to in memory session variables works best. 

It seems Acumatica uses cookies to maintain state. With apps I create with the ScriptBasic web server, the only cookie I use is its session ID. Everything else is stored in session variables pages processed refer to.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

I’m getting this error when running my script.

{"message":"An error has occurred.","exceptionMessage":"API Login Limit", …

The plan is once I move the code to the web server is do the login and check for when the access token expires. When working in the console, I need to login each time I run the script.

How can I get by this API Login Limit?

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

It looks like this demo / developer license limits the number of API logins. 🙁

Navigate to ‘SM604000 to see ‘Maximum Number of Concurrent Web Services API Requests’ and other API limitations of the instance. These limitations are based on the license of the instance of Acumatica and can be increased by upgrading to a higher level license.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

This is my license monitoring page.

 

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

This is the complete error message.

{"message":"An error has occurred.","exceptionMessage":"API Login Limit","exceptionType":"PX.Data.PXException","stackTrace":"   at PX.LicensePolicy.PXLicensePolicy.CheckApiUsersLimits(HttpContextBase c)\r\n   at PX.Data.PXLogin.LoginUserImpl(HttpContext httpContext, String userName, String password) in C:\\build\\code_repo\\NetTools\\PX.Data\\Access\\Login.cs:line 370\r\n   at PX.Data.PXLogin.PX.Data.IPXLogin.LoginUser(String& userName, String password) in C:\\build\\code_repo\\NetTools\\PX.Data\\Access\\Login.cs:line 265\r\n   at PX.Api.Services.LoginService.PX.Api.Services.ILoginService.Login(String login, String password, String company, String branch, String locale, String prefix) in C:\\build\\code_repo\\NetTools\\PX.Data\\Api\\Services\\LoginService.cs:line 130\r\n   at PX.Api.ContractBased.ILoginServiceExtensions.LoginForSoapApi(ILoginService loginService, IMultiFactorService multiFactorService, String login, String password, String company, String branch, String locale) in C:\\build\\code_repo\\NetTools\\PX.Data\\Api\\ILoginServiceExtensions.cs:line 22\r\n   at PX.Api.ContractBased.WebApi.Controllers.AuthController.Login(Credentials credentials)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()"}

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

When I tried my script this morning I didn't get the API Login Limit error. Can I get the story how this limit works?

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 30, 2025

I think I need to Logout as part of my script.

I still plan to incorporate the Token endpoint to refresh the access token so I don't have to keep logging. In / out.

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 31, 2025

I’m still trying to do a Logout endpoint REST call but it doesn’t seem to be working. I can only run the script twice (demo user limit) and have to restart the IIS application pool to clear the exceeded error.

 

ch = curl::init()
url = "http://localhost/acumaticadb/entity/auth/logout"
curl::option(ch, "URL", url)
curl::option(ch, "POST")
curl::option(ch, "HEADER")
curl::option(ch, "HTTPHEADER", "Authorization: Basic " & web::base64_encode("admin:PASSWORD"))
curl::option(ch, "HTTPHEADER", "Cookie: CompanyID=Demo")
curl::option(ch, "HTTPHEADER", "Content-Length: 0")
response = curl::perform(ch)                                        
curl::finish(ch)

PRINT response,"\n"

OUTPUT

HTTP/1.1 204 No Content
Cache-Control: private
Set-Cookie: ASP.NET_SessionId=aw3dhgurfu2es2vv04m4awy4; path=/; HttpOnly; SameSite=Lax
Set-Cookie: ASP.NET_SessionId=aw3dhgurfu2es2vv04m4awy4; path=/; HttpOnly; SameSite=Lax
Set-Cookie: requestid=6BE2CF8DF40088AF11F06E53EFC1BDC5; path=/
Set-Cookie: requeststat=+st:9+sc:~/entity/auth/logout+start:638895935259291211+tg:; path=/
Date: Thu, 31 Jul 2025 21:18:45 GMT


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • July 31, 2025

I posted my Logout endpoint code and header response which seems to have executed correctly. I'm waiting for the moderator to approve the post as it has code in it.

My guess is the Set-Cookie headers returned In the Logout endpoint needs to be seen by Acumatica to complete the Logout procedure.

Acumatica doesn't seem REST friendly unless you are using it within the Acumatica environment. External REST calls are useless for the most part. Please prove me wrong..

This sending of duplicate Set-Cookie headers needs to be fixed.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 1, 2025

In Postman I can send multiple Login endpoint and I don’t get the API Login Exceeded error.

Why is that?


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 1, 2025

In Postman the Logout seems to be working.

What am I missing in cURL that allows multiple Login calls and successfully does the Logout?


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 1, 2025

cURL has the ability to fake a cookie store. I’m wondering if Postman is doing the same?

 

Would the Acumatica REST API see my cURL cookie store and use it?

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 1, 2025

I'm going to give the cURL cookie store feature a try. It seems this is the solution and I don't have to worry about the duplicate Set-Cookie headers being sent.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 1, 2025

I'm assuming that the Login endpoint will just return if called with the same user credentials by seeing the cookies are already set in the cookie store. This prevent creating another session using the same credentials.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

It seems passing the stored cookies with the Cookie: header using the ​​​​​Login endpoint doesn't solve to user exceeded problem. It looks like that call only accepts cookies from the emulated cookie store. (like Postman)

Can someone confirm this before I start adding cookie store emulation to my extension module?

 

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

I needed to add to add the Authorization and CompanyID headers to the Login endpoint. When I do a Logout it looks like it succeeded and returns a few Set-Cookie headers in the response.

For whatever reason it's not releasing the session count and I can only login twice before getting the API Login Exceeded error. 

Once I'm logged in and use the cookie string I save to a file, I can access any of the Acumatica entity endpoints using that cookie string.

My guess at this point is the Logout call needs to see the Set-Cookie headers returned in its response. Since I'm not using the traditional cookie store emulation, Acumatica never sees those cookies and doesn't complete the Logout releasing the session. (guess)

Any help or advice how I can get around this issue would be much appreciated. I really don't want to add the cookie engine to my curl extension module.

This is the first REST interface I've worked with that uses cookies for authentication, expecting the interface to emulate a browser cookie store. The duplicate Set-Cookie headers were unexpected.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

What if I logged out twice using the returned Set-Cookie headers in the first call as a Cookie: header in the second attempt?

It would be ironic if the double Logout worked since Acumatica is sending duplicate Set-Cookie headers.

On a positive note, it only takes a half a second to return 126 customers in JSON in ScriptBasic running in a Windows console. I like to get the server based code tested in a console as it's easier to debug before I move the code to the web server.

 


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

I was able to get the Logout endpoint working as it should. I’m not using any emulated cookie store and only Set-Cookie headers. This script logs on, gets a customer by ID and finally logs out closing the session. The MakeCookie function eliminates duplicate Set-Cookie headers.

 

' Acumatica REST - Customer by ID

IMPORT curl.sbi
IMPORT webext.sbi
IMPORT t.sbi

FUNCTION MakeCookies(raw_cookies)
LOCAL headers, tmpstr, p1, p2, key, new_header, cookie_str, x, i
SPLITA raw_cookies BY "\n" TO headers
FOR x = 0 TO UBOUND(headers) -1
IF LEFT(headers[x], 11) = "Set-Cookie:" THEN
p1 = INSTR(headers[x], " ")
tmpstr = MID(headers[x], p1 + 1)
p2 = INSTR(tmpstr, "=")
key = LEFT(tmpstr, p2 -1)
new_header{key} = tmpstr
END IF
NEXT
cookie_str = ""
FOR i = 0 TO UBOUND(new_header) STEP 2
cookie_str &= LEFT(new_header[i + 1], INSTR(new_header[i + 1], ";")) & " "
NEXT
MakeCookies = RTRIM(cookie_str)
END FUNCTION

jstr = """
{
"name": "admin",
"password": "WordPass52!",
"company": "Demo"
}
"""

crumbs = t::LoadString("Acumatica.cookies")


' Login
PRINT "** Login **\n\n"
IF LEN(crumbs) = 0 THEN
ch = curl::init()
url = "http://localhost/acumaticadb/entity/auth/login"
curl::option(ch, "HEADER")
curl::option(ch, "URL", url)
curl::option(ch, "HTTPHEADER", "Content-Type: application/json")
curl::option(ch, "HTTPHEADER", "Authorization: Basic " & web::base64_encode("admin:WordPass52!"))
curl::option(ch, "POSTFIELDS", jstr)
response_headers = curl::perform(ch)
curl::finish(ch)
crumbs = MakeCookies(response_headers)
t::SaveString("C:\\Acumatica\\Acumatica.cookies", crumbs)
END IF


' Customer by ID
PRINT "**Customer **\n\n"
ch = curl::init()
url = "http://localhost/acumaticadb/entity/Default/24.200.001/Customer/ABARTENDE"
curl::option(ch, "URL", url)
curl::option(ch, "HTTPHEADER", "Content-Type: application/x-www-form-urlencoded")
curl::option(ch, "HTTPHEADER", "Cookie: " & crumbs)
json = curl::perform(ch)
curl::finish(ch)
web::json2sba(json)
web::sbadump(json, 0)
PRINTNL

' Logout
PRINT "** Logout **\n\n"
ch = curl::init()
url = "http://localhost/acumaticadb/entity/auth/logout"
curl::option(ch, "URL", url)
curl::option(ch, "POST")
curl::option(ch, "HEADER")
curl::option(ch, "HTTPHEADER", "Authorization: Basic " & web::base64_encode("admin:WordPass52!"))
curl::option(ch, "HTTPHEADER", "Cookie: " & crumbs)
curl::option(ch, "HTTPHEADER", "Content-Length: 0")
response_headers = curl::perform(ch)
curl::finish(ch)
t::SaveString("C:\\Acumatica\\Acumatica.cookies", "")

END

OUTPUT

C:\Acumatica>sbc getcust.sb
** Login **

**Customer **

id = 6a113b2c-d87f-e411-beca-00b56d0561c2
rowNumber = 1
note
   value =
ApplyOverdueCharges
   value = FALSE
AutoApplyPayments
   value = FALSE
BAccountID
   value = 4899
BillingAddressOverride
   value = TRUE
BillingContactOverride
   value = TRUE
CreatedDateTime
   value = 2023-12-31T16:00:00-08:00
CreditLimit
   value = 0
CurrencyID
   value = USD
CustomerCategory
   value = I
CustomerClass
   value = KEY
CustomerID
   value = ABARTENDE
CustomerName
   value = USA Bartending School
Email
   value = barkeep@usabartend.con
EnableCurrencyOverride
   value = TRUE
EnableRateOverride
   value = FALSE
EnableWriteOffs
   value = TRUE
EntityUsageType
   value = Default
LastModifiedDateTime
   value = 2023-12-31T16:00:00-08:00
LeadTimedays
   value = 0
LocationName
   value = Primary Location
MultiCurrencyStatements
   value = FALSE
NoteID
   value = 6a113b2c-d87f-e411-beca-00b56d0561c2
OrderPriority
   value = 10
PrimaryContactID
   value = 9977
PrintDunningLetters
   value = FALSE
PrintInvoices
   value = FALSE
PrintStatements
   value = FALSE
ResidentialDelivery
   value = FALSE
RestrictVisibilityTo
   value = PROD
SaturdayDelivery
   value = FALSE
SendDunningLettersbyEmail
   value = TRUE
SendInvoicesbyEmail
   value = TRUE
SendStatementsbyEmail
   value = FALSE
ShippingAddressOverride
   value = TRUE
ShippingContactOverride
   value = TRUE
ShippingRule
   value = Back Order Allowed
ShippingTerms
   value = CFR
StatementCycleID
   value = EOM
StatementType
   value = Open Item
Status
   value = Active
Terms
   value = 30D
WriteOffLimit
   value = 20
_links
   self = /acumaticadb/entity/Default/24.200.001/Customer/6a113b2c-d87f-e411-beca-00b56d0561c2
   files:put = /acumaticadb/entity/Default/24.200.001/files/PX.Objects.AR.CustomerMaint/BAccount/6a113b2c-d87f-e411-beca-00b56d0561c2/{filename}

** Logout **


C:\Acumatica>


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

Moderator,

I posted a working version of logging in, get customer by ID and logging out. I can run this script as many times as I want without API Login Exceeded errors.


JSpikowski
Jr Varsity II
Forum|alt.badge.img
  • Author
  • Jr Varsity II
  • August 2, 2025

It looks like the returned Set-Cookie headers in the Logout endpoint are used as a reference that the session has been closed and not needed to be seen by Acumatica's REST API.